blob: 283eef7c4c934fa52c06817e95a40a45f6db89b7 [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;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000133
134 /* If the keystroke buffer isn't empty, get out. */
135 if (key_buffer != NULL)
136 return;
137
138 /* Read in the first character using blocking input. */
139 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000140
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000141#ifndef NANO_SMALL
142 allow_pending_sigwinch(TRUE);
143#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000144 input = wgetch(win);
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000145#ifndef NANO_SMALL
146 allow_pending_sigwinch(FALSE);
147#endif
148
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000149 /* Increment the length of the keystroke buffer, save the value of
150 * the keystroke in key, and set key_code to TRUE if the keystroke
151 * is an extended keypad value and hence shouldn't be treated as a
152 * multibyte character. */
153 key_buffer_len++;
154 key_buffer = (buffer *)nmalloc(sizeof(buffer));
155 key_buffer[0].key = input;
156 key_buffer[0].key_code = !is_byte_char(input);
157
158 /* Read in the remaining characters using non-blocking input. */
159 nodelay(win, TRUE);
160
161 while (TRUE) {
162#ifndef NANO_SMALL
163 allow_pending_sigwinch(TRUE);
164#endif
165 input = wgetch(win);
166#ifndef NANO_SMALL
167 allow_pending_sigwinch(FALSE);
168#endif
169
170 /* If there aren't any more characters, stop reading. */
171 if (input == ERR)
172 break;
173
174 /* Otherwise, increment the length of the keystroke buffer, save
175 * the value of the keystroke in key, and set key_code to TRUE
176 * if the keystroke is an extended keypad value and hence
177 * shouldn't be treated as a multibyte character. */
178 key_buffer_len++;
179 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
180 sizeof(buffer));
181 key_buffer[key_buffer_len - 1].key = input;
182 key_buffer[key_buffer_len - 1].key_code = !is_byte_char(input);
183 }
184
185 /* Switch back to non-blocking input. */
186 nodelay(win, FALSE);
187
188#ifdef NANO_WIDE
189 if (!ISSET(NO_UTF8)) {
David Lawrence Ramseyf812e4f2004-12-07 17:35:14 +0000190 size_t i;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000191 buffer *clean_key_buffer = NULL;
192 size_t clean_key_buffer_len = 0;
193
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000194 /* Change all complete and valid multibyte keystrokes to
195 * their wide character values, discarding the others. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000196 for (i = 0; i < key_buffer_len; i++) {
197 wchar_t wide_key;
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000198 int wide_key_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000199
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000200 if (key_buffer[i].key_code) {
201 wide_key_len = 1;
202 wide_key = key_buffer[i].key;
203 } else
204 wide_key_len = mbtowc(&wide_key,
205 (const char *)&key_buffer[i].key, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000206
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000207 if (wide_key_len != -1) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000208 clean_key_buffer_len++;
209 clean_key_buffer = (buffer *)nrealloc(clean_key_buffer,
210 clean_key_buffer_len * sizeof(buffer));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000211
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000212 clean_key_buffer[clean_key_buffer_len - 1].key =
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000213 wide_key;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000214 clean_key_buffer[clean_key_buffer_len - 1].key_code =
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000215 key_buffer[i].key_code;
216 }
217 }
218
219 /* Replace the default keystroke buffer with the non-(-1)
220 * keystroke buffer. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000221 key_buffer_len = clean_key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000222 free(key_buffer);
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000223 key_buffer = clean_key_buffer;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000224 }
225#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000226}
227
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000228/* Return the length of the default keystroke buffer. */
229size_t get_buffer_len(void)
230{
231 return key_buffer_len;
232}
233
234/* Return the key values stored in the keystroke buffer input,
235 * discarding the key_code values in it. */
236int *buffer_to_keys(buffer *input, size_t input_len)
237{
238 int *sequence = (int *)nmalloc(input_len * sizeof(int));
239 size_t i;
240
241 for (i = 0; i < input_len; i++)
242 sequence[i] = input[i].key;
243
244 return sequence;
245}
246
247/* Add the contents of the keystroke buffer input to the default
248 * keystroke buffer. */
249void unget_input(buffer *input, size_t input_len)
250{
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000251 buffer *clean_input = NULL;
252 size_t clean_input_len = 0;
253
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000254#ifndef NANO_SMALL
255 allow_pending_sigwinch(TRUE);
256 allow_pending_sigwinch(FALSE);
257#endif
258
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000259#ifdef NANO_WIDE
260 if (!ISSET(NO_UTF8)) {
David Lawrence Ramseyf812e4f2004-12-07 17:35:14 +0000261 size_t i;
262
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000263 /* Keep all valid wide keystrokes, discarding the others. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000264 for (i = 0; i < input_len; i++) {
David Lawrence Ramseyeae97ca2004-12-07 22:24:03 +0000265 char key[MB_LEN_MAX];
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000266 int key_len = input[i].key_code ? 1 :
267 wctomb(key, input[i].key);
David Lawrence Ramseyeae97ca2004-12-07 22:24:03 +0000268
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000269 if (key_len != -1) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000270 clean_input_len++;
271 clean_input = (buffer *)nrealloc(clean_input,
272 clean_input_len * sizeof(buffer));
273
274 clean_input[clean_input_len - 1].key = input[i].key;
275 clean_input[clean_input_len - 1].key_code =
276 input[i].key_code;
277 }
278 }
279 } else {
280#endif
281 clean_input = input;
282 clean_input_len = input_len;
283#ifdef NANO_WIDE
284 }
285#endif
286
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000287 /* If input is empty, get out. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000288 if (clean_input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000289 return;
290
291 /* If adding input would put the default keystroke buffer beyond
292 * maximum capacity, only add enough of input to put it at maximum
293 * capacity. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000294 if (key_buffer_len + clean_input_len < key_buffer_len)
295 clean_input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000296
297 /* Add the length of input to the length of the default keystroke
298 * buffer, and reallocate the default keystroke buffer so that it
299 * has enough room for input. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000300 key_buffer_len += clean_input_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000301 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
302 sizeof(buffer));
303
304 /* If the default keystroke buffer wasn't empty before, move its
305 * beginning forward far enough so that we can add input to its
306 * beginning. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000307 if (key_buffer_len > clean_input_len)
308 memmove(key_buffer + clean_input_len, key_buffer,
309 (key_buffer_len - clean_input_len) * sizeof(buffer));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000310
311 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000312 memcpy(key_buffer, clean_input, clean_input_len * sizeof(buffer));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000313}
314
315/* Put back the character stored in kbinput. If func_key is TRUE and
316 * the character is out of byte range, interpret it as an extended
317 * keypad value. If meta_key is TRUE, put back the Escape character
318 * after putting back kbinput. */
319void unget_kbinput(int kbinput, bool meta_key, bool func_key)
320{
321 buffer input;
322
323 input.key = kbinput;
324 input.key_code = (func_key && !is_byte_char(kbinput));
325
326 unget_input(&input, 1);
327
328 if (meta_key) {
329 input.key = NANO_CONTROL_3;
330 input.key_code = FALSE;
331 unget_input(&input, 1);
332 }
333}
334
335/* Try to read input_len characters from the default keystroke buffer.
336 * If the default keystroke buffer is empty and win isn't NULL, try to
337 * read in more characters from win and add them to the default
338 * keystroke buffer before doing anything else. If the default
339 * keystroke buffer is empty and win is NULL, return NULL. */
340buffer *get_input(WINDOW *win, size_t input_len)
341{
342 buffer *input;
343
344#ifndef NANO_SMALL
345 allow_pending_sigwinch(TRUE);
346 allow_pending_sigwinch(FALSE);
347#endif
348
349 if (key_buffer_len == 0) {
350 if (win != NULL)
351 get_buffer(win);
352
353 if (key_buffer_len == 0)
354 return NULL;
355 }
356
357 /* If input_len is greater than the length of the default keystroke
358 * buffer, only read the number of characters in the default
359 * keystroke buffer. */
360 if (input_len > key_buffer_len)
361 input_len = key_buffer_len;
362
363 /* Subtract input_len from the length of the default keystroke
364 * buffer, and allocate the keystroke buffer input so that it
365 * has enough room for input_len keystrokes. */
366 key_buffer_len -= input_len;
367 input = (buffer *)nmalloc(input_len * sizeof(buffer));
368
369 /* Copy input_len characters from the beginning of the default
370 * keystroke buffer into input. */
371 memcpy(input, key_buffer, input_len * sizeof(buffer));
372
373 /* If the default keystroke buffer is empty, mark it as such. */
374 if (key_buffer_len == 0) {
375 free(key_buffer);
376 key_buffer = NULL;
377 /* If the default keystroke buffer isn't empty, move its
378 * beginning forward far enough back so that the keystrokes in input
379 * are no longer at its beginning. */
380 } else {
381 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
382 sizeof(buffer));
383 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
384 sizeof(buffer));
385 }
386
387 return input;
388}
389
390/* Read in a single character. If it's ignored, swallow it and go on.
391 * Otherwise, try to translate it from ASCII, meta key sequences, escape
392 * sequences, and/or extended keypad values. Set meta_key to TRUE when
393 * we get a meta key sequence, and set func_key to TRUE when we get an
394 * extended keypad value. Supported extended keypad values consist of
395 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
396 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
397 * the function keypad (F1-F16), and the numeric keypad with NumLock
398 * off. Assume nodelay(win) is FALSE. */
399int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
400{
401 int kbinput;
402
403 /* Read in a character and interpret it. Continue doing this until
404 * we get a recognized value or sequence. */
405 while ((kbinput = parse_kbinput(win, meta_key, func_key
406#ifndef NANO_SMALL
407 , FALSE
408#endif
409 )) == ERR);
410
411 return kbinput;
412}
413
414/* Translate ASCII characters, extended keypad values, and escape
415 * sequences into their corresponding key values. Set meta_key to TRUE
416 * when we get a meta key sequence, and set func_key to TRUE when we get
417 * a function key. Assume nodelay(win) is FALSE. */
418int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000419#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000420 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000421#endif
422 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000423
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000424{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +0000425 static int escapes = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000426 static int word_digits = 0;
427 buffer *kbinput;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000428 int retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000429
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000430 if (reset) {
431 escapes = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000432 word_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000433 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000434 }
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000435
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000436 *meta_key = FALSE;
437 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000438
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000439 /* Read in a character. */
440 while ((kbinput = get_input(win, 1)) == NULL);
441
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000442 if (kbinput->key_code || is_byte_char(kbinput->key)) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000443 /* If we got an extended keypad value or an ASCII character,
444 * translate it. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000445 switch (kbinput->key) {
446 case ERR:
447 break;
448 case NANO_CONTROL_3:
449 /* Increment the escape counter. */
450 escapes++;
451 switch (escapes) {
452 case 1:
453 /* One escape: wait for more input. */
454 case 2:
455 /* Two escapes: wait for more input. */
456 break;
457 default:
458 /* More than two escapes: reset the escape
459 * counter and wait for more input. */
460 escapes = 0;
461 }
462 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000463#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000464 /* Since we don't change the default SIGWINCH handler when
465 * NANO_SMALL is defined, KEY_RESIZE is never generated.
466 * Also, Slang and SunOS 5.7-5.9 don't support
467 * KEY_RESIZE. */
468 case KEY_RESIZE:
469 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000470#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000471#ifdef PDCURSES
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000472 case KEY_SHIFT_L:
473 case KEY_SHIFT_R:
474 case KEY_CONTROL_L:
475 case KEY_CONTROL_R:
476 case KEY_ALT_L:
477 case KEY_ALT_R:
478 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000479#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000480 default:
481 switch (escapes) {
482 case 0:
483 switch (kbinput->key) {
484 case NANO_CONTROL_8:
485 retval = ISSET(REBIND_DELETE) ?
486 NANO_DELETE_KEY :
487 NANO_BACKSPACE_KEY;
488 break;
489 case KEY_DOWN:
490 retval = NANO_NEXTLINE_KEY;
491 break;
492 case KEY_UP:
493 retval = NANO_PREVLINE_KEY;
494 break;
495 case KEY_LEFT:
496 retval = NANO_BACK_KEY;
497 break;
498 case KEY_RIGHT:
499 retval = NANO_FORWARD_KEY;
500 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000501#ifdef KEY_HOME
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000502 /* HP-UX 10 and 11 don't support
503 * KEY_HOME. */
504 case KEY_HOME:
505 retval = NANO_HOME_KEY;
506 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000507#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000508 case KEY_BACKSPACE:
509 retval = NANO_BACKSPACE_KEY;
510 break;
511 case KEY_DC:
512 retval = ISSET(REBIND_DELETE) ?
513 NANO_BACKSPACE_KEY :
514 NANO_DELETE_KEY;
515 break;
516 case KEY_IC:
517 retval = NANO_INSERTFILE_KEY;
518 break;
519 case KEY_NPAGE:
520 retval = NANO_NEXTPAGE_KEY;
521 break;
522 case KEY_PPAGE:
523 retval = NANO_PREVPAGE_KEY;
524 break;
525 case KEY_ENTER:
526 retval = NANO_ENTER_KEY;
527 break;
528 case KEY_A1: /* Home (7) on numeric
529 * keypad with NumLock
530 * off. */
531 retval = NANO_HOME_KEY;
532 break;
533 case KEY_A3: /* PageUp (9) on numeric
534 * keypad with NumLock
535 * off. */
536 retval = NANO_PREVPAGE_KEY;
537 break;
538 case KEY_B2: /* Center (5) on numeric
539 * keypad with NumLock
540 * off. */
541 break;
542 case KEY_C1: /* End (1) on numeric
543 * keypad with NumLock
544 * off. */
545 retval = NANO_END_KEY;
546 break;
547 case KEY_C3: /* PageDown (4) on
548 * numeric keypad with
549 * NumLock off. */
550 retval = NANO_NEXTPAGE_KEY;
551 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000552#ifdef KEY_BEG
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000553 /* Slang doesn't support KEY_BEG. */
554 case KEY_BEG: /* Center (5) on numeric
555 * keypad with NumLock
556 * off. */
557 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000558#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000559#ifdef KEY_END
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000560 /* HP-UX 10 and 11 don't support KEY_END. */
561 case KEY_END:
562 retval = NANO_END_KEY;
563 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000564#endif
565#ifdef KEY_SUSPEND
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000566 /* Slang doesn't support KEY_SUSPEND. */
567 case KEY_SUSPEND:
568 retval = NANO_SUSPEND_KEY;
569 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000570#endif
571#ifdef KEY_SLEFT
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000572 /* Slang doesn't support KEY_SLEFT. */
573 case KEY_SLEFT:
574 retval = NANO_BACK_KEY;
575 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000576#endif
577#ifdef KEY_SRIGHT
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000578 /* Slang doesn't support KEY_SRIGHT. */
579 case KEY_SRIGHT:
580 retval = NANO_FORWARD_KEY;
581 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000582#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000583 default:
584 retval = kbinput->key;
585 break;
586 }
587 break;
588 case 1:
589 /* One escape followed by a non-escape: escape
590 * sequence mode. Reset the escape counter. If
591 * there aren't any other keys waiting, we have
592 * a meta key sequence, so set meta_key to TRUE
593 * and save the lowercase version of the
594 * non-escape character as the result. If there
595 * are other keys waiting, we have a true escape
596 * sequence, so interpret it. */
597 escapes = 0;
598 if (get_buffer_len() == 0) {
599 *meta_key = TRUE;
600 retval = tolower(kbinput->key);
601 } else {
602 buffer *escape_kbinput;
603 int *sequence;
604 size_t seq_len;
605 bool ignore_seq;
606
607 /* Put back the non-escape character, get
608 * the complete escape sequence, translate
609 * its key values into the corresponding key
610 * value, and save that as the result. */
611 unget_input(kbinput, 1);
612 seq_len = get_buffer_len();
613 escape_kbinput = get_input(NULL, seq_len);
614 sequence = buffer_to_keys(escape_kbinput,
615 seq_len);
616 retval = get_escape_seq_kbinput(sequence,
617 seq_len, &ignore_seq);
618
619 /* If the escape sequence is unrecognized
620 * and not ignored, put back all of its
621 * characters except for the initial
622 * escape. */
623 if (retval == ERR && !ignore_seq)
624 unget_input(escape_kbinput, seq_len);
625
626 free(escape_kbinput);
627 }
628 break;
629 case 2:
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000630 /* Two escapes followed by one or more decimal
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000631 * digits: word sequence mode. If the word
632 * sequence's range is limited to 6XXXX (the
633 * first digit is in the '0' to '6' range and
634 * it's the first digit, or it's in the '0' to
635 * '9' range and it's not the first digit),
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000636 * increment the word sequence counter and
637 * interpret the digit. If the word sequence's
638 * range is not limited to 6XXXX, fall
639 * through. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000640 if (('0' <= kbinput->key && kbinput->key <= '6'
641 && word_digits == 0) ||
642 ('0' <= kbinput->key && kbinput->key <= '9'
643 && word_digits > 0)) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000644 int word_kbinput;
645
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000646 word_digits++;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000647 word_kbinput = get_word_kbinput(kbinput->key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000648#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000649 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000650#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000651 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000652
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000653 if (word_kbinput != ERR) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000654 /* If we've read in a complete word
655 * sequence, reset the word sequence
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000656 * counter and the escape counter,
657 * and put back the corresponding word
658 * value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000659 word_digits = 0;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000660 escapes = 0;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000661 unget_kbinput(word_kbinput, FALSE,
662 FALSE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000663 }
664 } else {
665 /* Reset the escape counter. */
666 escapes = 0;
667 if (word_digits == 0)
668 /* Two escapes followed by a non-decimal
669 * digit or a decimal digit that would
670 * create a word sequence greater than
671 * 6XXXX, and we're not in the middle of
672 * a word sequence: control character
673 * sequence mode. Interpret the control
674 * sequence and save the corresponding
675 * control character as the result. */
676 retval = get_control_kbinput(kbinput->key);
677 else {
678 /* If we're in the middle of a word
679 * sequence, reset the word sequence
680 * counter and save the character we got
681 * as the result. */
682 word_digits = 0;
683 retval = kbinput->key;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000684 }
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000685 }
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000686 break;
687 }
688 }
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000689
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000690 /* If we have a result and it's an extended keypad value, set
691 * func_key to TRUE. */
692 if (retval != ERR)
693 *func_key = !is_byte_char(retval);
694 } else
695 /* If we didn't get an extended keypad value or an ASCII
696 * character, leave it as-is. */
697 retval = kbinput->key;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000698
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000699#ifdef DEBUG
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000700 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 +0000701#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000702
703 /* Return the result. */
704 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000705}
706
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000707/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000708 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000709 * are generated when the keypad doesn't support the needed keys. If
710 * the escape sequence is recognized but we want to ignore it, return
711 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
712 * set ignore_seq to FALSE. Assume that Escape has already been read
713 * in. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000714int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000715 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000716{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000717 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000718
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000719 *ignore_seq = FALSE;
720
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000721 if (seq_len > 1) {
722 switch (sequence[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000723 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000724 switch (sequence[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000725 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000726 if (seq_len >= 3) {
727 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000728 case 'P': /* Esc O 2 P == F13 on
729 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000730 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000731 break;
732 case 'Q': /* Esc O 2 Q == F14 on
733 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000734 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000735 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000736 case 'R': /* Esc O 2 R == F15 on
737 * xterm. */
738 retval = KEY_F(15);
739 break;
740 case 'S': /* Esc O 2 S == F16 on
741 * xterm. */
742 retval = KEY_F(16);
743 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000744 }
745 }
746 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000747 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
748 case 'B': /* Esc O B == Down on
749 * VT100/VT320/xterm. */
750 case 'C': /* Esc O C == Right on
751 * VT100/VT320/xterm. */
752 case 'D': /* Esc O D == Left on
753 * VT100/VT320/xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000754 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000755 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000756 case 'E': /* Esc O E == Center (5) on numeric keypad
757 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000758 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000759 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000760 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000761 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000762 break;
763 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000764 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000765 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000766 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000767 * NumLock off on VT100/VT220/VT320/xterm/
768 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000769 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000770 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000771 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000772 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000773 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000774 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000775 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000776 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000777 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000778 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000779 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000780 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000781 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000782 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000783 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000784 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000785 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000786 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000787 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000788 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000789 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000790 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000791 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000792 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000793 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000794 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000795 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000796 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000797 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000798 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000799 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000800 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000801 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000802 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000803 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000804 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000805 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000806 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000807 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000808 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000809 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000810 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000811 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000812 * NumLock off on VT100/VT220/VT320/xterm/
813 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000814 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000815 break;
816 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000817 * NumLock off on VT100/VT220/VT320/xterm/
818 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000819 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000820 break;
821 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000822 * NumLock off on VT100/VT220/VT320/xterm/
823 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000824 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000825 break;
826 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000827 * NumLock off on VT100/VT220/VT320/xterm/
828 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000829 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000830 break;
831 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000832 * with NumLock off on VT100/VT220/VT320/
833 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000834 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000835 break;
836 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000837 * NumLock off on VT100/VT220/VT320/xterm/
838 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000839 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000840 break;
841 case 'p': /* Esc O p == Insert (0) 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_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000845 break;
846 case 'q': /* Esc O q == End (1) 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_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000850 break;
851 case 'r': /* Esc O r == Down (2) 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_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000855 break;
856 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000857 * keypad with NumLock off on VT100/VT220/
858 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000859 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000860 break;
861 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000862 * with NumLock off on VT100/VT220/VT320/
863 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000864 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000865 break;
866 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000867 * with NumLock off on VT100/VT220/VT320/
868 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000869 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000870 break;
871 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000872 * with NumLock off on VT100/VT220/VT320/
873 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000874 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000875 break;
876 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000877 * with NumLock off on VT100/VT220/VT320/
878 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000879 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000880 break;
881 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000882 * with NumLock off on VT100/VT220/VT320/
883 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000884 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000885 break;
886 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000887 * with NumLock off on VT100/VT220/VT320/
888 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000889 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000890 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000891 }
892 break;
893 case 'o':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000894 switch (sequence[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000895 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000896 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000897 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000898 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000899 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000900 break;
901 }
902 break;
903 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000904 switch (sequence[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000905 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000906 if (seq_len >= 3) {
907 switch (sequence[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000908 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
909 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000910 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000911 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000912 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
913 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000914 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000915 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000916 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
917 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000918 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000919 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000920 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
921 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000922 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000923 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000924 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
925 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000926 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000927 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000928 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000929 * VT220/VT320/Linux console/
930 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000931 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000932 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000933 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000934 * VT220/VT320/Linux console/
935 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000936 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000937 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000938 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000939 * VT220/VT320/Linux console/
940 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000941 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000942 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000943 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000944 if (seq_len >= 4) {
945 switch (sequence[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000946 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000947 if (seq_len >= 5) {
948 switch (sequence[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000949 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
950 * xterm. */
951 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
952 * xterm. */
953 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
954 * xterm. */
955 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
956 * xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000957 retval = get_escape_seq_abcd(sequence[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000958 break;
959 }
960 }
961 break;
962 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000963 if (seq_len >= 5) {
964 switch (sequence[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000965 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
966 * xterm. */
967 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
968 * xterm. */
969 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
970 * xterm. */
971 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
972 * xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000973 retval = get_escape_seq_abcd(sequence[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000974 break;
975 }
976 }
977 break;
978 }
979 }
980 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000981 default: /* Esc [ 1 ~ == Home on
982 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000983 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000984 break;
985 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000986 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000987 break;
988 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000989 if (seq_len >= 3) {
990 switch (sequence[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000991 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000992 * VT220/VT320/Linux console/
993 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000994 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000995 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000996 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000997 * VT220/VT320/Linux console/
998 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000999 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001000 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001001 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001002 * VT220/VT320/Linux console/
1003 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001004 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001005 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001006 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001007 * VT220/VT320/Linux console/
1008 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001009 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001010 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001011 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001012 * VT220/VT320/Linux console/
1013 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001014 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001015 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001016 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001017 * VT220/VT320/Linux console/
1018 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001019 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001020 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +00001021 case '8': /* Esc [ 2 8 ~ == F15 on
1022 * VT220/VT320/Linux console/
1023 * rxvt/Eterm. */
1024 retval = KEY_F(15);
1025 break;
1026 case '9': /* Esc [ 2 9 ~ == F16 on
1027 * VT220/VT320/Linux console/
1028 * rxvt/Eterm. */
1029 retval = KEY_F(16);
1030 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001031 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001032 * VT220/VT320/Linux console/
1033 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001034 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001035 break;
1036 }
1037 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001038 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001039 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
1040 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001041 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001042 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001043 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001044 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001045 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001046 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001047 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
1048 * Linux console/xterm; Esc [ 5 ^ ==
1049 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001050 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001051 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001052 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
1053 * Linux console/xterm; Esc [ 6 ^ ==
1054 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001055 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001056 break;
1057 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001058 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001059 break;
1060 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001062 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001063 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001064 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001065 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001066 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001067 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001068 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001069 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001070 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001071 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001072 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001073 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001074 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001075 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001076 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001077 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001078 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001079 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001080 * rxvt/Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001081 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001082 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001083 case 'E': /* Esc [ E == Center (5) on numeric keypad
1084 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +00001085 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001086 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001087 case 'F': /* Esc [ F == End on FreeBSD
1088 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001089 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001090 break;
1091 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001092 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001093 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001094 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001095 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001096 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001097 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001098 break;
1099 case 'I': /* Esc [ I == PageUp on FreeBSD
1100 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001101 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001102 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001103 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001104 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001105 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001106 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001107 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001108 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001109 break;
1110 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001111 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001112 break;
1113 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001114 if (seq_len >= 3) {
1115 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001116 case 'P': /* Esc [ O P == F1 on
1117 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001118 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001119 break;
1120 case 'Q': /* Esc [ O Q == F2 on
1121 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001122 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001123 break;
1124 case 'R': /* Esc [ O R == F3 on
1125 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001126 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001127 break;
1128 case 'S': /* Esc [ O S == F4 on
1129 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001130 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001131 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001132 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001133 } else {
1134 /* Esc [ O == F3 on FreeBSD console. */
1135 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001136 }
1137 break;
1138 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001139 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001140 break;
1141 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001142 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001143 break;
1144 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001145 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001146 break;
1147 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001148 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001149 break;
1150 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001151 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001152 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001153 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001154 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001155 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001156 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001157 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001158 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001159 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001160 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001161 break;
1162 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001163 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001164 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001165 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001166 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001167 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001168 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001169 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001170 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001171 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001172 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001173 case 'c': /* Esc [ c == Shift-Right on rxvt/
1174 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001175 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001176 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001177 break;
1178 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001179 if (seq_len >= 3) {
1180 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001181 case 'A': /* Esc [ [ A == F1 on Linux
1182 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001183 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001184 break;
1185 case 'B': /* Esc [ [ B == F2 on Linux
1186 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001187 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001188 break;
1189 case 'C': /* Esc [ [ C == F3 on Linux
1190 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001191 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001192 break;
1193 case 'D': /* Esc [ [ D == F4 on Linux
1194 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001195 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001196 break;
1197 case 'E': /* Esc [ [ E == F5 on Linux
1198 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001199 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001200 break;
1201 }
1202 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001203 break;
1204 }
1205 break;
1206 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001207 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001208
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001209#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001210 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001211#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001212
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001213 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001214}
1215
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001216/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001217 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001218 * to many escape sequences. */
1219int get_escape_seq_abcd(int kbinput)
1220{
1221 switch (tolower(kbinput)) {
1222 case 'a':
1223 return NANO_PREVLINE_KEY;
1224 case 'b':
1225 return NANO_NEXTLINE_KEY;
1226 case 'c':
1227 return NANO_FORWARD_KEY;
1228 case 'd':
1229 return NANO_BACK_KEY;
1230 default:
1231 return ERR;
1232 }
1233}
1234
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001235/* Translate a word sequence: turn a three-digit decimal number from
1236 * 000 to 255 into its corresponding word value. */
1237int get_word_kbinput(int kbinput
1238#ifndef NANO_SMALL
1239 , bool reset
1240#endif
1241 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001242{
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001243 static int word_digits = 0;
1244 static int word_kbinput = 0;
1245 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001246
1247#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001248 if (reset) {
1249 word_digits = 0;
1250 word_kbinput = 0;
1251 return ERR;
1252 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001253#endif
1254
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001255 /* Increment the word digit counter. */
1256 word_digits++;
1257
1258 switch (word_digits) {
1259 case 1:
1260 /* One digit: reset the word sequence holder and add the
1261 * digit we got to the 10000's position of the word sequence
1262 * holder. */
1263 word_kbinput = 0;
1264 if ('0' <= kbinput && kbinput <= '6')
1265 word_kbinput += (kbinput - '0') * 10000;
1266 else
1267 /* If the character we got isn't a decimal digit, or if
1268 * it is and it would put the word sequence out of word
1269 * range, save it as the result. */
1270 retval = kbinput;
1271 break;
1272 case 2:
1273 /* Two digits: add the digit we got to the 1000's position
1274 * of the word sequence holder. */
1275 if (('0' <= kbinput && kbinput <= '5') ||
1276 (word_kbinput < 60000 && '6' <= kbinput &&
1277 kbinput <= '9'))
1278 word_kbinput += (kbinput - '0') * 1000;
1279 else
1280 /* If the character we got isn't a decimal digit, or if
1281 * it is and it would put the word sequence out of word
1282 * range, save it as the result. */
1283 retval = kbinput;
1284 break;
1285 case 3:
1286 /* Three digits: add the digit we got to the 100's position
1287 * of the word sequence holder. */
1288 if (('0' <= kbinput && kbinput <= '5') ||
1289 (word_kbinput < 65000 && '6' <= kbinput &&
1290 kbinput <= '9'))
1291 word_kbinput += (kbinput - '0') * 100;
1292 else
1293 /* If the character we got isn't a decimal digit, or if
1294 * it is and it would put the word sequence out of word
1295 * range, save it as the result. */
1296 retval = kbinput;
1297 break;
1298 case 4:
1299 /* Four digits: add the digit we got to the 10's position of
1300 * the word sequence holder. */
1301 if (('0' <= kbinput && kbinput <= '3') ||
1302 (word_kbinput < 65500 && '4' <= kbinput &&
1303 kbinput <= '9'))
1304 word_kbinput += (kbinput - '0') * 10;
1305 else
1306 /* If the character we got isn't a decimal digit, or if
1307 * it is and it would put the word sequence out of word
1308 * range, save it as the result. */
1309 retval = kbinput;
1310 break;
1311 case 5:
1312 /* Five digits: add the digit we got to the 1's position of
1313 * the word sequence holder, and save the corresponding word
1314 * value as the result. */
1315 if (('0' <= kbinput && kbinput <= '5') ||
1316 (word_kbinput < 65530 && '6' <= kbinput &&
1317 kbinput <= '9')) {
1318 word_kbinput += (kbinput - '0');
1319 retval = word_kbinput;
1320 } else
1321 /* If the character we got isn't a decimal digit, or if
1322 * it is and it would put the word sequence out of word
1323 * range, save it as the result. */
1324 retval = kbinput;
1325 break;
1326 default:
1327 /* More than three digits: save the character we got as the
1328 * result. */
1329 retval = kbinput;
1330 break;
1331 }
1332
1333 /* If we have a result, reset the word digit counter and the word
1334 * sequence holder. */
1335 if (retval != ERR) {
1336 word_digits = 0;
1337 word_kbinput = 0;
1338 }
1339
1340#ifdef DEBUG
1341 fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word_kbinput = %d, retval = %d\n", kbinput, word_digits, word_kbinput, retval);
1342#endif
1343
1344 return retval;
1345}
1346
1347/* Translate a control character sequence: turn an ASCII non-control
1348 * character into its corresponding control character. */
1349int get_control_kbinput(int kbinput)
1350{
1351 int retval;
1352
1353 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1354 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1355 kbinput == '`')
1356 retval = NANO_CONTROL_SPACE;
1357 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1358 else if ('3' <= kbinput && kbinput <= '7')
1359 retval = kbinput - 24;
1360 /* Ctrl-8 (Ctrl-?) */
1361 else if (kbinput == '8' || kbinput == '?')
1362 retval = NANO_CONTROL_8;
1363 /* Ctrl-A to Ctrl-_ */
1364 else if ('A' <= kbinput && kbinput <= '_')
1365 retval = kbinput - 64;
1366 /* Ctrl-a to Ctrl-~ */
1367 else if ('a' <= kbinput && kbinput <= '~')
1368 retval = kbinput - 96;
1369 else
1370 retval = kbinput;
1371
1372#ifdef DEBUG
1373 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1374#endif
1375
1376 return retval;
1377}
1378
1379/* Read in a string of characters verbatim, and return the length of the
1380 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1381int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1382{
1383 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001384
1385 /* Turn off flow control characters if necessary so that we can type
1386 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001387 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001388 if (ISSET(PRESERVE))
1389 disable_flow_control();
1390 keypad(win, FALSE);
1391
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001392 /* Read in a stream of characters and interpret it if possible. */
1393 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001394
1395 /* Turn flow control characters back on if necessary and turn the
1396 * keypad back on now that we're done. */
1397 if (ISSET(PRESERVE))
1398 enable_flow_control();
1399 keypad(win, TRUE);
1400
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001401 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001402}
1403
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001404/* Read in a stream of all available characters. Translate the first
1405 * few characters of the input into the corresponding word value if
1406 * possible. After that, leave the input as-is. */
1407int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001408{
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001409 buffer *kbinput, *sequence;
1410 int word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001411
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001412 /* Read in the first keystroke. */
1413 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001414
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001415 /* Check whether the first keystroke is a decimal digit. */
1416 word = get_word_kbinput(kbinput->key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001417#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001418 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001419#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001420 );
1421
1422 /* If the first keystroke isn't a decimal digit, put back the first
1423 * keystroke. */
1424 if (word != ERR)
1425 unget_input(kbinput, 1);
1426 /* Otherwise, read in keystrokes until we have a complete word
1427 * sequence, and put back the corresponding word value. */
1428 else {
1429 buffer word_kbinput;
1430
1431 while (word == ERR) {
1432 while ((kbinput = get_input(win, 1)) == NULL);
1433 word = get_word_kbinput(kbinput->key
1434#ifndef NANO_SMALL
1435 , FALSE
1436#endif
1437 );
1438 }
1439
1440 word_kbinput.key = word;
1441 word_kbinput.key_code = FALSE;
1442
1443 unget_input(&word_kbinput, 1);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001444 }
1445
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001446 /* Get the complete sequence, and save the key values in it as the
1447 * result. */
1448 *kbinput_len = get_buffer_len();
1449 sequence = get_input(NULL, *kbinput_len);
1450 retval = buffer_to_keys(sequence, *kbinput_len);
1451 free(sequence);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001452
1453 return retval;
1454}
1455
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001456#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001457/* Check for a mouse event, and if one's taken place, save the
1458 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001459 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1460 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001461 * place on it, figure out which shortcut was clicked and put back the
1462 * equivalent keystroke(s). Return FALSE if no keystrokes were
1463 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001464 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001465bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001466{
1467 MEVENT mevent;
1468
1469 *mouse_x = -1;
1470 *mouse_y = -1;
1471
1472 /* First, get the actual mouse event. */
1473 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001474 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001475
1476 /* Save the screen coordinates where the mouse event took place. */
1477 *mouse_x = mevent.x;
1478 *mouse_y = mevent.y;
1479
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001480 /* If we're allowing shortcuts, the current shortcut list is being
1481 * displayed on the last two lines of the screen, and the mouse
1482 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001483 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001484 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1485 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001486 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001487 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001488 /* The number of shortcuts in the current shortcut list. */
1489 const shortcut *s = currshortcut;
1490 /* The actual shortcut we clicked on, starting at the first
1491 * one in the current shortcut list. */
1492
1493 /* Get the shortcut lists' length. */
1494 if (currshortcut == main_list)
1495 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001496 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001497 currslen = length_of_list(currshortcut);
1498
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001499 /* We don't show any more shortcuts than the main list
1500 * does. */
1501 if (currslen > MAIN_VISIBLE)
1502 currslen = MAIN_VISIBLE;
1503 }
1504
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001505 /* Calculate the width of each shortcut in the list (it's the
1506 * same for all of them). */
1507 if (currslen < 2)
1508 i = COLS / 6;
1509 else
1510 i = COLS / ((currslen / 2) + (currslen % 2));
1511
1512 /* Calculate the y-coordinates relative to the beginning of
1513 * bottomwin, i.e, the bottom three lines of the screen. */
1514 j = *mouse_y - (editwinrows + 3);
1515
1516 /* If we're on the statusbar, beyond the end of the shortcut
1517 * list, or beyond the end of a shortcut on the right side of
1518 * the screen, don't do anything. */
1519 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001520 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001521 j = (*mouse_x / i) * 2 + j;
1522 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001523 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001524
1525 /* Go through the shortcut list to determine which shortcut was
1526 * clicked. */
1527 for (; j > 0; j--)
1528 s = s->next;
1529
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001530 /* And put back the equivalent key. Assume that each shortcut
1531 * has, at the very least, an equivalent control key, an
1532 * equivalent primary meta key sequence, or both. */
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001533 if (s->ctrlval != NANO_NO_KEY)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001534 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001535 else if (s->metaval != NANO_NO_KEY)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001536 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001537
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001538 return TRUE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001539 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001540 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001541}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001542#endif /* !DISABLE_MOUSE */
1543
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001544const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001545 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001546{
1547 const shortcut *s = s_list;
1548 size_t slen = length_of_list(s_list);
1549
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001550#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001551 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 +00001552#endif
1553
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001554 /* Check for shortcuts. */
1555 for (; slen > 0; slen--) {
1556 /* We've found a shortcut if:
1557 *
1558 * 1. The key exists.
1559 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001560 * 3. meta_key is TRUE and the key is the primary or
1561 * miscellaneous meta sequence in the shortcut list.
1562 * 4. func_key is TRUE and the key is a function key in the
1563 * shortcut list. */
1564
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001565 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1566 (*meta_key == TRUE && (*kbinput == s->metaval ||
1567 *kbinput == s->miscval)) || (*func_key == TRUE &&
1568 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001569 break;
1570 }
1571
1572 s = s->next;
1573 }
1574
1575 /* Translate the shortcut to either its control key or its meta key
1576 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001577 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001578 if (slen > 0) {
1579 if (s->ctrlval != NANO_NO_KEY) {
1580 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001581 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001582 *kbinput = s->ctrlval;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001583 } else if (s->metaval != NANO_NO_KEY) {
1584 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001585 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001586 *kbinput = s->metaval;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001587 }
1588 return s;
1589 }
1590
1591 return NULL;
1592}
1593
1594#ifndef NANO_SMALL
1595const toggle *get_toggle(int kbinput, bool meta_key)
1596{
1597 const toggle *t = toggles;
1598
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001599#ifdef DEBUG
1600 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1601#endif
1602
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001603 /* Check for toggles. */
1604 for (; t != NULL; t = t->next) {
1605 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001606 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001607 if (meta_key && kbinput == t->val)
1608 break;
1609 }
1610
1611 return t;
1612}
1613#endif /* !NANO_SMALL */
1614
Chris Allegretta6df90f52002-07-19 01:08:59 +00001615/* Return the placewewant associated with current_x. That is, xplustabs
1616 * is the zero-based column position of the cursor. Value is no smaller
1617 * than current_x. */
1618size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001619{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001620 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001621}
1622
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001623/* actual_x() gives the index in str of the character displayed at
1624 * column xplus. That is, actual_x() is the largest value such that
1625 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
1626size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001627{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001628 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00001629 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001630 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00001631 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001632
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001633 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001634
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001635 for (; length < xplus && *str != '\0'; i++, str++) {
1636 if (*str == '\t')
David Lawrence Ramsey0362c582003-09-30 03:31:56 +00001637 length += tabsize - (length % tabsize);
David Lawrence Ramsey1601c282004-10-21 22:06:40 +00001638 else if (is_cntrl_char(*str))
Chris Allegretta6df90f52002-07-19 01:08:59 +00001639 length += 2;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001640 else
1641 length++;
1642 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001643 assert(length == strnlenpt(str - i, i));
1644 assert(i <= strlen(str - i));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001645
Chris Allegretta6df90f52002-07-19 01:08:59 +00001646 if (length > xplus)
1647 i--;
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001648
Chris Allegretta6df90f52002-07-19 01:08:59 +00001649 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00001650}
1651
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00001652/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001653 * columns wide are the first size characters of buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001654size_t strnlenpt(const char *buf, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00001655{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001656 size_t length = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001657
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001658 assert(buf != NULL);
1659 for (; *buf != '\0' && size != 0; size--, buf++) {
1660 if (*buf == '\t')
1661 length += tabsize - (length % tabsize);
David Lawrence Ramsey1601c282004-10-21 22:06:40 +00001662 else if (is_cntrl_char(*buf))
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001663 length += 2;
1664 else
1665 length++;
1666 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001667 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001668}
1669
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001670/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001671size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001672{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00001673 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001674}
1675
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001676void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001677{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001678 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001679}
1680
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001681void blank_edit(void)
1682{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001683 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001684 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001685 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001686}
1687
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001688void blank_statusbar(void)
1689{
1690 mvwaddstr(bottomwin, 0, 0, hblank);
1691}
1692
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001693void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001694{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001695 if (statusblank > 1)
1696 statusblank--;
1697 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
1698 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001699 blank_statusbar();
1700 wnoutrefresh(bottomwin);
1701 reset_cursor();
1702 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001703 }
1704}
1705
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001706void blank_bottombars(void)
1707{
1708 if (!ISSET(NO_HELP)) {
1709 mvwaddstr(bottomwin, 1, 0, hblank);
1710 mvwaddstr(bottomwin, 2, 0, hblank);
1711 }
1712}
1713
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001714/* Convert buf into a string that can be displayed on screen. The
1715 * caller wants to display buf starting with column start_col, and
1716 * extending for at most len columns. start_col is zero-based. len is
1717 * one-based, so len == 0 means you get "" returned. The returned
1718 * string is dynamically allocated, and should be freed. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001719char *display_string(const char *buf, size_t start_col, size_t len)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001720{
1721 size_t start_index;
1722 /* Index in buf of first character shown in return value. */
1723 size_t column;
1724 /* Screen column start_index corresponds to. */
1725 size_t end_index;
1726 /* Index in buf of last character shown in return value. */
1727 size_t alloc_len;
1728 /* The length of memory allocated for converted. */
1729 char *converted;
1730 /* The string we return. */
1731 size_t index;
1732 /* Current position in converted. */
1733
1734 if (len == 0)
1735 return mallocstrcpy(NULL, "");
1736
1737 start_index = actual_x(buf, start_col);
1738 column = strnlenpt(buf, start_index);
1739 assert(column <= start_col);
1740 end_index = actual_x(buf, start_col + len - 1);
1741 alloc_len = strnlenpt(buf, end_index + 1) - column;
1742 if (len > alloc_len + column - start_col)
1743 len = alloc_len + column - start_col;
1744 converted = charalloc(alloc_len + 1);
1745 buf += start_index;
1746 index = 0;
1747
1748 for (; index < alloc_len; buf++) {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001749 if (*buf == '\t') {
1750 converted[index++] =
1751#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
1752 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
1753#endif
1754 ' ';
1755 while ((column + index) % tabsize)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001756 converted[index++] = ' ';
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001757 } else if (is_cntrl_char(*buf)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001758 converted[index++] = '^';
1759 if (*buf == '\n')
1760 /* Treat newlines embedded in a line as encoded nulls;
1761 * the line in question should be run through unsunder()
1762 * before reaching here. */
1763 converted[index++] = '@';
1764 else if (*buf == NANO_CONTROL_8)
1765 converted[index++] = '?';
1766 else
1767 converted[index++] = *buf + 64;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001768 } else if (*buf == ' ')
1769 converted[index++] =
1770#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
1771 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
1772#endif
1773 ' ';
1774 else
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001775 converted[index++] = *buf;
1776 }
1777 assert(len <= alloc_len + column - start_col);
1778 charmove(converted, converted + start_col - column, len);
1779 null_at(&converted, len);
1780
1781 return charealloc(converted, len + 1);
1782}
1783
Chris Allegretta7662c862003-01-13 01:35:15 +00001784/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001785 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00001786 *
Chris Allegretta7662c862003-01-13 01:35:15 +00001787 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00001788 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001789void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001790{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001791 size_t x_real = strnlenpt(inputbuf, x);
1792 int wid = COLS - strlen(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00001793
Chris Allegretta6df90f52002-07-19 01:08:59 +00001794 assert(0 <= x && x <= strlen(inputbuf));
1795
Chris Allegrettab3655b42001-10-22 03:15:31 +00001796 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001797 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001798
Chris Allegretta6df90f52002-07-19 01:08:59 +00001799 mvwaddstr(bottomwin, 0, 0, buf);
1800 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001801
1802 if (COLS > 1)
1803 waddch(bottomwin, x_real < wid ? ' ' : '$');
1804 if (COLS > 2) {
1805 size_t page_start = x_real - x_real % wid;
1806 char *expanded = display_string(inputbuf, page_start, wid);
1807
1808 assert(wid > 0);
1809 assert(strlen(expanded) <= wid);
1810 waddstr(bottomwin, expanded);
1811 free(expanded);
1812 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
1813 } else
1814 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001815 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001816}
1817
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00001818/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00001819 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00001820int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00001821#ifndef NANO_SMALL
1822 historyheadtype *history_list,
1823#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00001824 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00001825#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001826 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00001827#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00001828 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00001829{
1830 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001831 bool meta_key, func_key;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001832 static size_t x = (size_t)-1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001833 /* the cursor position in 'answer' */
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001834 size_t xend;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001835 /* length of 'answer', the status bar text */
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001836 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001837 /* used by input_tab() */
1838 const shortcut *t;
Chris Allegretta598106e2002-01-19 01:59:37 +00001839
Chris Allegretta5beed502003-01-05 20:41:21 +00001840#ifndef NANO_SMALL
1841 /* for history */
1842 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00001843 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00001844 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001845 int last_kbinput = 0;
1846
1847 /* This variable is used in the search history code. use_cb == 0
1848 means that we're using the existing history and ignoring
1849 currentbuf. use_cb == 1 means that the entry in answer should be
1850 moved to currentbuf or restored from currentbuf to answer.
1851 use_cb == 2 means that the entry in currentbuf should be moved to
1852 answer or restored from answer to currentbuf. */
1853 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00001854#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001855 xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00001856
David Lawrence Ramsey4dd723a2004-10-05 02:29:52 +00001857 /* Only put x at the end of the string if it's uninitialized, if it
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00001858 would be past the end of the string as it is, or if
1859 resetstatuspos is TRUE. Otherwise, leave it alone. This is so
1860 the cursor position stays at the same place if a prompt-changing
1861 toggle is pressed. */
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001862 if (x == (size_t)-1 || x > xend || resetstatuspos)
Chris Allegretta09fc4302003-01-16 22:16:38 +00001863 x = xend;
1864
Chris Allegrettae1e0fd62003-04-15 01:15:09 +00001865 answer = charealloc(answer, xend + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001866 if (xend > 0)
1867 strcpy(answer, def);
1868 else
1869 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001870
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00001871#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001872 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00001873#endif
1874
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001875 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00001876
Chris Allegretta6df90f52002-07-19 01:08:59 +00001877 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001878
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001879 /* Make sure any editor screen updates are displayed before getting
1880 input */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00001881 wnoutrefresh(edit);
1882 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00001883
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001884 /* If we're using restricted mode, we aren't allowed to change the
1885 * name of a file once it has one because that would allow writing
1886 * to files not specified on the command line. In this case,
1887 * disable all keys that would change the text if the filename isn't
1888 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001889 while ((kbinput = get_kbinput(bottomwin, &meta_key, &func_key)) !=
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001890 NANO_CANCEL_KEY && kbinput != NANO_ENTER_KEY) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001891 for (t = s; t != NULL; t = t->next) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001892#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001893 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001894#endif
1895
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001896 /* Temporary hack to interpret NANO_HELP_FKEY correctly. */
1897 if (kbinput == t->funcval)
1898 kbinput = t->ctrlval;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00001899
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001900 if (kbinput == t->ctrlval && is_cntrl_char(kbinput)) {
Chris Allegretta5bf51d32000-11-16 06:01:10 +00001901
Chris Allegrettab3655b42001-10-22 03:15:31 +00001902#ifndef DISABLE_HELP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001903 /* Have to do this here, it would be too late to do it
1904 in statusq() */
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00001905 if (kbinput == NANO_HELP_KEY) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00001906 do_help();
1907 break;
1908 }
1909#endif
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001910#ifndef NANO_SMALL
1911 /* Have to handle these here too, for the time being */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001912 if (kbinput == NANO_PREVLINE_KEY || kbinput == NANO_NEXTLINE_KEY)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001913 break;
1914#endif
Chris Allegretta5af58892003-01-17 21:07:38 +00001915
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001916 return t->ctrlval;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001917 }
1918 }
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001919 assert(x <= xend && xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001920
Chris Allegretta04d848e2000-11-05 17:54:41 +00001921 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001922 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00001923
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001924 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00001925#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001926 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001927 {
1928 int mouse_x, mouse_y;
1929 get_mouseinput(&mouse_x, &mouse_y, TRUE);
1930 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001931 break;
1932#endif
David Lawrence Ramsey72d8e542004-09-25 00:45:07 +00001933 case NANO_REFRESH_KEY:
1934 total_refresh();
1935 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00001936 case NANO_HOME_KEY:
David Lawrence Ramseyc7acf692004-05-22 20:15:20 +00001937#ifndef NANO_SMALL
1938 if (ISSET(SMART_HOME)) {
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001939 size_t old_x = x;
David Lawrence Ramseyc7acf692004-05-22 20:15:20 +00001940
1941 for (x = 0; isblank(answer[x]) && x < xend; x++)
1942 ;
1943
1944 if (x == old_x || x == xend)
1945 x = 0;
1946 } else
1947#endif
1948 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001949 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00001950 case NANO_END_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001951 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001952 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00001953 case NANO_FORWARD_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001954 if (x < xend)
1955 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001956 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001957 case NANO_DELETE_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001958 /* If we're using restricted mode, the filename isn't blank,
1959 * and we're at the "Write File" prompt, disable Delete. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001960 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1961 if (x < xend) {
1962 charmove(answer + x, answer + x + 1, xend - x);
1963 xend--;
1964 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001965 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001966 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001967 case NANO_CUT_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001968 /* If we're using restricted mode, the filename isn't blank,
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00001969 * and we're at the "Write File" prompt, disable Cut. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001970 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1971 null_at(&answer, 0);
1972 xend = 0;
1973 x = 0;
1974 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001975 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001976 case NANO_BACKSPACE_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001977 /* If we're using restricted mode, the filename isn't blank,
1978 * and we're at the "Write File" prompt, disable
1979 * Backspace. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001980 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1981 if (x > 0) {
1982 charmove(answer + x - 1, answer + x, xend - x + 1);
1983 x--;
1984 xend--;
1985 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001986 }
Chris Allegretta04d848e2000-11-05 17:54:41 +00001987 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001988 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001989#ifndef NANO_SMALL
1990 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00001991 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001992 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001993 history_list->current = (historytype *)history_list;
1994 history_list->len = strlen(answer);
1995 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001996
Chris Allegretta7662c862003-01-13 01:35:15 +00001997 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001998 complete = get_history_completion(history_list, answer);
1999 xend = strlen(complete);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002000 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002001 answer = mallocstrcpy(answer, complete);
2002 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002003 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002004#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002005 else
2006#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002007#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002008#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002009 if (allow_tabs) {
Chris Allegretta327abda2003-01-17 05:04:17 +00002010 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002011
Chris Allegretta327abda2003-01-17 05:04:17 +00002012 answer = input_tab(answer, x, &tabbed, &shift, list);
2013 xend = strlen(answer);
2014 x += shift;
2015 if (x > xend)
2016 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002017 }
2018#endif
2019 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00002020 case NANO_BACK_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00002021 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002022 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002023 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002024 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002025#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002026 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002027
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002028 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2029 isn't NULL, and currentbuf is different from answer,
2030 it means that we're scrolling up at the top of the
2031 search history, and we need to save the current
2032 answer in currentbuf; do this and reset use_cb to
2033 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002034 if (currentbuf == NULL || (use_cb == 1 &&
2035 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002036 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002037 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002038 }
2039
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002040 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2041 is different from answer, it means that we're
2042 scrolling up at the bottom of the search history, and
2043 we need to make the string in currentbuf the current
2044 answer; do this, blow away currentbuf since we don't
2045 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002046 if (currentbuf != NULL && use_cb == 2 &&
2047 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002048 answer = mallocstrcpy(answer, currentbuf);
2049 free(currentbuf);
2050 currentbuf = NULL;
2051 xend = strlen(answer);
2052 use_cb = 0;
2053
2054 /* else get older search from the history list and save
2055 it in answer; if there is no older search, blank out
2056 answer */
2057 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002058 answer = mallocstrcpy(answer, history);
2059 xend = strlen(history);
2060 } else {
2061 answer = mallocstrcpy(answer, "");
2062 xend = 0;
2063 }
2064 x = xend;
2065 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002066#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002067 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002068 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002069#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002070 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002071
2072 /* get newer search from the history list and save it
2073 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002074 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002075 answer = mallocstrcpy(answer, history);
2076 xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002077
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002078 /* if there is no newer search, we're here */
2079
2080 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2081 that we're scrolling down at the bottom of the search
2082 history and we need to make the string in currentbuf
2083 the current answer; do this, blow away currentbuf
2084 since we don't need it anymore, and set use_cb to
2085 1 */
2086 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002087 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002088 free(currentbuf);
2089 currentbuf = NULL;
2090 xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002091 use_cb = 1;
2092
2093 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2094 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002095 the search history and the current answer (if it's
2096 not blank) needs to be saved in currentbuf; do this,
2097 blank out answer (if necessary), and set use_cb to
2098 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002099 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002100 if (answer[0] != '\0') {
2101 currentbuf = mallocstrcpy(currentbuf, answer);
2102 answer = mallocstrcpy(answer, "");
2103 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002104 xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002105 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002106 }
2107 x = xend;
2108 }
2109#endif
2110 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00002111 default:
2112
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002113 for (t = s; t != NULL; t = t->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +00002114#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002115 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
Chris Allegretta598106e2002-01-19 01:59:37 +00002116 kbinput);
Chris Allegretta658399a2001-06-14 02:54:22 +00002117#endif
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002118 if (meta_key && (kbinput == t->metaval || kbinput == t->miscval))
David Lawrence Ramsey32613fa2004-05-24 18:40:41 +00002119 /* We hit a meta key. Do like above. We don't
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00002120 * just put back the letter and let it get
David Lawrence Ramsey82138502003-12-24 08:03:54 +00002121 * caught above cause that screws the
2122 * keypad... */
2123 return kbinput;
Chris Allegretta658399a2001-06-14 02:54:22 +00002124 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002125
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002126 /* If we're using restricted mode, the filename isn't blank,
2127 * and we're at the "Write File" prompt, act as though the
2128 * unhandled character we got is a control character and
2129 * throw it away. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00002130 if (is_cntrl_char(kbinput) || (ISSET(RESTRICTED) && filename[0] != '\0' && s == writefile_list))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002131 break;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002132 answer = charealloc(answer, xend + 2);
David Lawrence Ramsey9eff7462003-09-16 02:04:00 +00002133 charmove(answer + x + 1, answer + x, xend - x + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002134 xend++;
2135 answer[x] = kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002136 x++;
2137
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002138#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002139 fprintf(stderr, "input \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002140#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002141 } /* switch (kbinput) */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002142#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002143 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002144#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00002145 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002146 wrefresh(bottomwin);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002147 } /* while (kbinput ...) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002148
Chris Allegretta5af58892003-01-17 21:07:38 +00002149 /* We finished putting in an answer; reset x */
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00002150 x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002151
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002152 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002153}
2154
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002155/* Ask a question on the statusbar. Answer will be stored in answer
2156 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2157 * otherwise, the valid shortcut key caught. def is any editable text
2158 * we want to put up by default.
2159 *
2160 * New arg tabs tells whether or not to allow tab completion. */
2161int statusq(bool allow_tabs, const shortcut *s, const char *def,
2162#ifndef NANO_SMALL
2163 historyheadtype *which_history,
2164#endif
2165 const char *msg, ...)
2166{
2167 va_list ap;
2168 char *foo = charalloc(COLS - 3);
2169 int ret;
2170#ifndef DISABLE_TABCOMP
2171 bool list = FALSE;
2172#endif
2173
2174 bottombars(s);
2175
2176 va_start(ap, msg);
2177 vsnprintf(foo, COLS - 4, msg, ap);
2178 va_end(ap);
2179 foo[COLS - 4] = '\0';
2180
2181 ret = nanogetstr(allow_tabs, foo, def,
2182#ifndef NANO_SMALL
2183 which_history,
2184#endif
2185 s
2186#ifndef DISABLE_TABCOMP
2187 , &list
2188#endif
2189 );
2190 free(foo);
2191 resetstatuspos = FALSE;
2192
2193 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002194 case NANO_FIRSTLINE_KEY:
2195 case NANO_FIRSTLINE_FKEY:
2196 do_first_line();
2197 resetstatuspos = TRUE;
2198 break;
2199 case NANO_LASTLINE_KEY:
2200 case NANO_LASTLINE_FKEY:
2201 do_last_line();
2202 resetstatuspos = TRUE;
2203 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002204#ifndef DISABLE_JUSTIFY
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002205 case NANO_PARABEGIN_KEY:
2206 case NANO_PARABEGIN_ALTKEY1:
2207 case NANO_PARABEGIN_ALTKEY2:
2208 do_para_begin();
2209 resetstatuspos = TRUE;
2210 break;
2211 case NANO_PARAEND_KEY:
2212 case NANO_PARAEND_ALTKEY1:
2213 case NANO_PARAEND_ALTKEY2:
2214 do_para_end();
2215 resetstatuspos = TRUE;
2216 break;
2217 case NANO_FULLJUSTIFY_KEY:
2218 case NANO_FULLJUSTIFY_ALTKEY:
2219 if (!ISSET(VIEW_MODE))
2220 do_full_justify();
2221 resetstatuspos = TRUE;
2222 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002223#endif
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002224 case NANO_CANCEL_KEY:
2225 ret = -1;
2226 resetstatuspos = TRUE;
2227 break;
2228 case NANO_ENTER_KEY:
2229 ret = (answer[0] == '\0') ? -2 : 0;
2230 resetstatuspos = TRUE;
2231 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002232 }
2233 blank_statusbar();
2234
2235#ifdef DEBUG
2236 fprintf(stderr, "I got \"%s\"\n", answer);
2237#endif
2238
2239#ifndef DISABLE_TABCOMP
2240 /* if we've done tab completion, there might be a list of
2241 filename matches on the edit window at this point; make sure
2242 they're cleared off. */
2243 if (list)
2244 edit_refresh();
2245#endif
2246
2247 return ret;
2248}
2249
2250void statusq_abort(void)
2251{
2252 resetstatuspos = TRUE;
2253}
2254
Chris Allegrettaf717f982003-02-13 22:25:01 +00002255void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002256{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002257 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002258 /* The space we have available for display. */
2259 size_t verlen = strlen(VERMSG) + 1;
2260 /* The length of the version message. */
2261 const char *prefix;
2262 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2263 size_t prefixlen;
2264 /* strlen(prefix) + 1. */
2265 const char *state;
2266 /* "Modified", "View", or spaces the length of "Modified".
2267 * Tells the state of this buffer. */
2268 size_t statelen = 0;
2269 /* strlen(state) + 1. */
2270 char *exppath = NULL;
2271 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002272 size_t exppathlen = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002273 /* strlen(exppath) + 1. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002274 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002275 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002276 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002277 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002278
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002279 assert(path != NULL || filename != NULL);
2280 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002281
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002282 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002283
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002284 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002285
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002286 if (COLS <= 5 || COLS - 5 < verlen)
2287 space = 0;
2288 else {
2289 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002290 /* Reserve 2/3 of the screen plus one column for after the
2291 * version message. */
2292 if (space < COLS - (COLS / 3) + 1)
2293 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002294 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002295
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002296 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002297 /* The version message should only take up 1/3 of the screen
2298 * minus one column. */
2299 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002300 waddstr(topwin, " ");
2301 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002302
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002303 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002304 state = _("Modified");
2305 else if (path == NULL && ISSET(VIEW_MODE))
2306 state = _("View");
2307 else {
2308 if (space > 0)
2309 statelen = strnlen(_("Modified"), space - 1) + 1;
2310 state = &hblank[COLS - statelen];
2311 }
2312 statelen = strnlen(state, COLS);
2313 /* We need a space before state. */
2314 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2315 statelen++;
2316
2317 assert(space >= 0);
2318 if (space == 0 || statelen >= space)
2319 goto the_end;
2320
2321#ifndef DISABLE_BROWSER
2322 if (path != NULL)
2323 prefix = _("DIR:");
2324 else
2325#endif
2326 if (filename[0] == '\0') {
2327 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002328 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002329 } else
2330 prefix = _("File:");
2331 assert(statelen < space);
2332 prefixlen = strnlen(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002333 /* If newfie is FALSE, we need a space after prefix. */
2334 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002335 prefixlen++;
2336
2337 if (path == NULL)
2338 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002339 if (space >= prefixlen + statelen)
2340 space -= prefixlen + statelen;
2341 else
2342 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002343 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002344 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002345 size_t lenpt = strlenpt(path), start_col;
2346
2347 if (lenpt > space)
2348 start_col = actual_x(path, lenpt - space);
2349 else
2350 start_col = 0;
2351 exppath = display_string(path, start_col, space);
2352 dots = (lenpt > space);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002353 exppathlen = strlen(exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002354 }
2355
2356 if (!dots) {
2357 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002358 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002359 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002360 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002361 assert(strlen(prefix) + 1 == prefixlen);
2362 waddch(topwin, ' ');
2363 waddstr(topwin, exppath);
2364 }
2365 } else {
2366 /* We will say something like "File: ...ename". */
2367 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002368 if (space == 0 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002369 goto the_end;
2370 waddch(topwin, ' ');
2371 waddnstr(topwin, "...", space);
2372 if (space <= 3)
2373 goto the_end;
2374 space -= 3;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002375 assert(exppathlen == space + 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002376 waddnstr(topwin, exppath + 3, space);
2377 }
2378
2379 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002380 free(exppath);
2381
2382 if (COLS <= 1 || statelen >= COLS - 1)
2383 mvwaddnstr(topwin, 0, 0, state, COLS);
2384 else {
2385 assert(COLS - statelen - 2 >= 0);
2386 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2387 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2388 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002389
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002390 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002391
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002392 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002393 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002394 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002395}
2396
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002397/* If modified is not already set, set it and update titlebar. */
2398void set_modified(void)
2399{
2400 if (!ISSET(MODIFIED)) {
2401 SET(MODIFIED);
2402 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002403 }
2404}
2405
2406void statusbar(const char *msg, ...)
2407{
2408 va_list ap;
2409
2410 va_start(ap, msg);
2411
2412 /* Curses mode is turned off. If we use wmove() now, it will muck
2413 * up the terminal settings. So we just use vfprintf(). */
2414 if (curses_ended) {
2415 vfprintf(stderr, msg, ap);
2416 va_end(ap);
2417 return;
2418 }
2419
2420 /* Blank out the line. */
2421 blank_statusbar();
2422
2423 if (COLS >= 4) {
2424 char *bar;
2425 char *foo;
2426 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002427#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002428 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002429 UNSET(WHITESPACE_DISPLAY);
2430#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002431 bar = charalloc(COLS - 3);
2432 vsnprintf(bar, COLS - 3, msg, ap);
2433 va_end(ap);
2434 foo = display_string(bar, 0, COLS - 4);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002435#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2436 if (old_whitespace)
2437 SET(WHITESPACE_DISPLAY);
2438#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002439 free(bar);
2440 foo_len = strlen(foo);
2441 start_x = (COLS - foo_len - 4) / 2;
2442
2443 wmove(bottomwin, 0, start_x);
2444 wattron(bottomwin, A_REVERSE);
2445
2446 waddstr(bottomwin, "[ ");
2447 waddstr(bottomwin, foo);
2448 free(foo);
2449 waddstr(bottomwin, " ]");
2450 wattroff(bottomwin, A_REVERSE);
2451 wnoutrefresh(bottomwin);
2452 reset_cursor();
2453 wrefresh(edit);
2454 /* Leave the cursor at its position in the edit window, not
2455 * in the statusbar. */
2456 }
2457
2458 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002459 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002460}
2461
Chris Allegretta6232d662002-05-12 19:52:15 +00002462void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002463{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002464 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002465
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002466 if (ISSET(NO_HELP))
2467 return;
2468
Chris Allegretta6232d662002-05-12 19:52:15 +00002469 if (s == main_list) {
2470 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002471 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002472 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002473 slen = length_of_list(s);
2474
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002475 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002476 if (slen > MAIN_VISIBLE)
2477 slen = MAIN_VISIBLE;
2478 }
2479
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002480 /* There will be this many characters per column. We need at least
2481 * 3 to display anything properly.*/
2482 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002483
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002484 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002485
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002486 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002487 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002488
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002489 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002490#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002491 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002492 keystr = _("Up");
2493 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002494#endif
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002495 char foo[4];
Chris Allegretta658399a2001-06-14 02:54:22 +00002496
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002497 if (s->ctrlval == NANO_CONTROL_SPACE)
2498 strcpy(foo, "^ ");
2499 else if (s->ctrlval == NANO_CONTROL_8)
2500 strcpy(foo, "^?");
2501 /* Normal values. Assume that the shortcut has an
2502 * equivalent control key, meta key sequence, or both. */
2503 else if (s->ctrlval != NANO_NO_KEY)
2504 sprintf(foo, "^%c", s->ctrlval + 64);
2505 else if (s->metaval != NANO_NO_KEY)
2506 sprintf(foo, "M-%c", toupper(s->metaval));
2507
2508 keystr = foo;
2509#ifndef NANO_SMALL
2510 }
2511#endif
2512
2513 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002514 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002515 }
2516
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002517 wnoutrefresh(bottomwin);
2518 reset_cursor();
2519 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002520}
2521
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002522/* Write a shortcut key to the help area at the bottom of the window.
2523 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2524 * to write at most len characters, even if len is very small and
2525 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2526 * the whole string! We do not bother padding the entry with blanks. */
2527void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002528{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002529 assert(keystroke != NULL && desc != NULL && len >= 0);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002530 wattron(bottomwin, A_REVERSE);
2531 waddnstr(bottomwin, keystroke, len);
2532 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002533 len -= strlen(keystroke) + 1;
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002534 if (len > 0) {
2535 waddch(bottomwin, ' ');
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002536 waddnstr(bottomwin, desc, len);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002537 }
2538}
2539
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002540/* And so start the display update routines. */
2541
2542#ifndef NDEBUG
2543int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002544{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002545 int check_line = 0;
2546 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002547
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002548 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
2549 check_line++;
2550 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002551}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002552#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00002553
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002554/* nano scrolls horizontally within a line in chunks. This function
2555 * returns the column number of the first character displayed in the
2556 * window when the cursor is at the given column. Note that
2557 * 0 <= column - get_page_start(column) < COLS. */
2558size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002559{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002560 assert(COLS > 0);
2561 if (column == 0 || column < COLS - 1)
2562 return 0;
2563 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002564 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002565 else if (COLS > 2)
2566 return column - (COLS - 2);
2567 else
2568 return column - (COLS - 1);
2569 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002570}
2571
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002572/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002573 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002574void reset_cursor(void)
2575{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002576 /* If we haven't opened any files yet, put the cursor in the top
2577 * left corner of the edit window and get out. */
2578 if (edittop == NULL || current == NULL) {
2579 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002580 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002581 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002582
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002583 current_y = current->lineno - edittop->lineno;
2584 if (current_y < editwinrows) {
2585 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002586 wmove(edit, current_y, x - get_page_start(x));
2587 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002588}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002589
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002590/* edit_add() takes care of the job of actually painting a line into the
2591 * edit window. fileptr is the line to be painted, at row yval of the
2592 * window. converted is the actual string to be written to the window,
2593 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00002594 * characters. start is the column number of the first character of
2595 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002596 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002597void edit_add(const filestruct *fileptr, const char *converted, int
2598 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002599{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002600#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
2601 size_t startpos = actual_x(fileptr->data, start);
2602 /* The position in fileptr->data of the leftmost character
2603 * that displays at least partially on the window. */
2604 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2605 /* The position in fileptr->data of the first character that is
2606 * completely off the window to the right.
2607 *
2608 * Note that endpos might be beyond the null terminator of the
2609 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002610#endif
2611
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002612 assert(fileptr != NULL && converted != NULL);
2613 assert(strlen(converted) <= COLS);
2614
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002615 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002616 * just the text that needs it). */
2617 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002618
Chris Allegretta7dd77682001-12-08 19:52:28 +00002619#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00002620 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002621 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002622
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002623 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2624 int x_start;
2625 /* Starting column for mvwaddnstr. Zero-based. */
2626 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002627 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002628 * characters on a whole line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002629 regmatch_t startmatch; /* match position for start_regexp */
2630 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002631
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002632 if (tmpcolor->bright)
2633 wattron(edit, A_BOLD);
2634 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002635 /* Two notes about regexec(). Return value 0 means there is
2636 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002637 * after the match. */
2638
2639 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002640 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002641 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002642
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002643 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002644 * last match. Even though two matches may overlap, we
2645 * want to ignore them, so that we can highlight
2646 * C-strings correctly. */
2647 while (k < endpos) {
2648 /* Note the fifth parameter to regexec(). It says
2649 * not to match the beginning-of-line character
2650 * unless k is 0. If regexec() returns REG_NOMATCH,
2651 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00002652 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002653 &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002654 break;
2655 /* Translate the match to the beginning of the line. */
2656 startmatch.rm_so += k;
2657 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002658 if (startmatch.rm_so == startmatch.rm_eo) {
2659 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00002660 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002661 } else if (startmatch.rm_so < endpos &&
2662 startmatch.rm_eo > startpos) {
2663 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002664 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002665 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002666 x_start = strnlenpt(fileptr->data,
2667 startmatch.rm_so) - start;
2668 paintlen = strnlenpt(fileptr->data,
2669 startmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002670 if (paintlen > COLS - x_start)
2671 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002672
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002673 assert(0 <= x_start && 0 < paintlen &&
2674 x_start + paintlen <= COLS);
2675 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002676 converted + x_start, paintlen);
2677 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002678 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002679 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002680 } else {
2681 /* This is a multi-line regexp. There are two steps.
2682 * First, we have to see if the beginning of the line is
2683 * colored by a start on an earlier line, and an end on
2684 * this line or later.
2685 *
2686 * We find the first line before fileptr matching the
2687 * start. If every match on that line is followed by an
2688 * end, then go to step two. Otherwise, find the next line
2689 * after start_line matching the end. If that line is not
2690 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002691
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002692 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002693 /* the first line before fileptr matching start */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002694 regoff_t start_col;
2695 /* where it starts in that line */
2696 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002697
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002698 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00002699 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002700 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002701 /* If there is an end on this line, there is no need
2702 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002703 if (regexec(tmpcolor->end, start_line->data, 0,
2704 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002705 goto step_two;
2706 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002707 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002708 /* No start found, so skip to the next step. */
2709 if (start_line == NULL)
2710 goto step_two;
2711 /* Now start_line is the first line before fileptr
2712 * containing a start match. Is there a start on this
2713 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002714
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002715 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002716 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002717 start_col += startmatch.rm_so;
2718 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002719 if (regexec(tmpcolor->end,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002720 start_line->data + start_col + startmatch.rm_eo,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002721 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
2722 REG_NOTBOL) == REG_NOMATCH)
2723 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002724 break;
2725 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002726 if (regexec(&tmpcolor->start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002727 start_line->data + start_col, 1,
2728 &startmatch, REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002729 /* No later start on this line. */
2730 goto step_two;
2731 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002732 /* Indeed, there is a start not followed on this line by
2733 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002734
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002735 /* We have already checked that there is no end before
2736 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002737 * the start at all? We don't paint unterminated
2738 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002739 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002740 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00002741 regexec(tmpcolor->end, end_line->data, 1,
2742 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002743 end_line = end_line->next;
2744
2745 /* No end found, or it is too early. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002746 if (end_line == NULL ||
2747 (end_line == fileptr && endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002748 goto step_two;
2749
2750 /* Now paint the start of fileptr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002751 paintlen = end_line != fileptr ? COLS :
2752 strnlenpt(fileptr->data, endmatch.rm_eo) - start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002753 if (paintlen > COLS)
2754 paintlen = COLS;
2755
2756 assert(0 < paintlen && paintlen <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002757 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002758
2759 /* We have already painted the whole line. */
2760 if (paintlen == COLS)
2761 goto skip_step_two;
2762
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002763 step_two:
2764 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002765 start_col = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002766 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002767 if (regexec(&tmpcolor->start,
2768 fileptr->data + start_col, 1, &startmatch,
2769 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
2770 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002771 /* No more starts on this line. */
2772 break;
2773 /* Translate the match to be relative to the
2774 * beginning of the line. */
2775 startmatch.rm_so += start_col;
2776 startmatch.rm_eo += start_col;
2777
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002778 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002779 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002780 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002781 x_start = strnlenpt(fileptr->data,
2782 startmatch.rm_so) - start;
2783 if (regexec(tmpcolor->end,
2784 fileptr->data + startmatch.rm_eo, 1, &endmatch,
2785 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002786 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002787 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002788 endmatch.rm_so += startmatch.rm_eo;
2789 endmatch.rm_eo += startmatch.rm_eo;
2790 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002791 * appear on this page, and is the match more
2792 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002793 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002794 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002795 paintlen = strnlenpt(fileptr->data,
2796 endmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002797 if (x_start + paintlen > COLS)
2798 paintlen = COLS - x_start;
2799
2800 assert(0 <= x_start && 0 < paintlen &&
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002801 x_start + paintlen <= COLS);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002802 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002803 converted + x_start, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002804 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002805 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002806 /* There is no end on this line. But we haven't
2807 * yet looked for one on later lines. */
2808 end_line = fileptr->next;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002809 while (end_line != NULL &&
2810 regexec(tmpcolor->end, end_line->data, 0,
2811 NULL, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002812 end_line = end_line->next;
2813 if (end_line != NULL) {
2814 assert(0 <= x_start && x_start < COLS);
2815 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002816 converted + x_start, COLS - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002817 /* We painted to the end of the line, so
2818 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002819 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002820 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002821 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002822 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002823 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002824 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002825
Chris Allegrettace452fb2003-02-03 02:56:44 +00002826 skip_step_two:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002827 wattroff(edit, A_BOLD);
2828 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
2829 } /* for tmpcolor in colorstrings */
2830 }
Chris Allegretta598106e2002-01-19 01:59:37 +00002831#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002832
Chris Allegretta7dd77682001-12-08 19:52:28 +00002833#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002834 if (ISSET(MARK_ISSET)
2835 && (fileptr->lineno <= mark_beginbuf->lineno
2836 || fileptr->lineno <= current->lineno)
2837 && (fileptr->lineno >= mark_beginbuf->lineno
2838 || fileptr->lineno >= current->lineno)) {
2839 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002840
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002841 const filestruct *top;
2842 /* Either current or mark_beginbuf, whichever is first. */
2843 size_t top_x;
2844 /* current_x or mark_beginx, corresponding to top. */
2845 const filestruct *bot;
2846 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002847 int x_start;
2848 /* Starting column for mvwaddnstr. Zero-based. */
2849 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002850 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002851 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002852
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00002853 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002854
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002855 if (top->lineno < fileptr->lineno || top_x < startpos)
2856 top_x = startpos;
2857 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2858 bot_x = endpos;
2859
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002860 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002861 if (top_x < endpos && bot_x > startpos) {
2862 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002863
2864 /* x_start is the expanded location of the beginning of the
2865 * mark minus the beginning of the page. */
2866 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002867
2868 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002869 /* If the end of the mark is off the page, paintlen is
2870 * -1, meaning that everything on the line gets
2871 * painted. */
2872 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002873 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002874 /* Otherwise, paintlen is the expanded location of the
2875 * end of the mark minus the expanded location of the
2876 * beginning of the mark. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002877 paintlen = strnlenpt(fileptr->data, bot_x)
2878 - (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002879
2880 /* If x_start is before the beginning of the page, shift
2881 * paintlen x_start characters to compensate, and put
2882 * x_start at the beginning of the page. */
2883 if (x_start < 0) {
2884 paintlen += x_start;
2885 x_start = 0;
2886 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002887
2888 assert(x_start >= 0 && x_start <= strlen(converted));
2889
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002890 wattron(edit, A_REVERSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002891 mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002892 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002893 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002894 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002895#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002896}
2897
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002898/* Just update one line in the edit buffer. Basically a wrapper for
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002899 * edit_add().
2900 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002901 * If fileptr != current, then index is considered 0. The line will be
2902 * displayed starting with fileptr->data[index]. Likely args are
2903 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002904void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002905{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002906 int line;
2907 /* line in the edit window for CURSES calls */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002908 char *converted;
2909 /* fileptr->data converted to have tabs and control characters
2910 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002911 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002912
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002913 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002914
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002915 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002916
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002917 /* We assume the line numbers are valid. Is that really true? */
2918 assert(line < 0 || line == check_linenumbers(fileptr));
2919
2920 if (line < 0 || line >= editwinrows)
2921 return;
2922
2923 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002924 mvwaddstr(edit, line, 0, hblank);
2925
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002926 /* Next, convert variables that index the line to their equivalent
2927 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002928 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002929 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002930
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002931 /* Expand the line, replacing Tab by spaces, and control characters
2932 * by their display form. */
2933 converted = display_string(fileptr->data, page_start, COLS);
Robert Siemborski53875912000-06-16 04:25:30 +00002934
Chris Allegretta4dc03d52002-05-11 03:04:44 +00002935 /* Now, paint the line */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002936 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002937 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002938
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002939 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002940 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002941 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002942 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002943}
2944
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002945/* Return a nonzero value if we need an update after moving
2946 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002947 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002948int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002949{
2950 return
2951#ifndef NANO_SMALL
2952 ISSET(MARK_ISSET) ||
2953#endif
2954 get_page_start(old_pww) != get_page_start(placewewant);
2955}
2956
2957/* Return a nonzero value if we need an update after moving vertically.
2958 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002959 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002960int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002961{
2962 return
2963#ifndef NANO_SMALL
2964 ISSET(MARK_ISSET) ||
2965#endif
2966 get_page_start(old_pww) != get_page_start(placewewant);
2967}
2968
2969/* Scroll the edit window in the given direction and the given number
2970 * of lines, and draw new lines on the blank lines left after the
2971 * scrolling. direction is the direction to scroll, either UP or DOWN,
2972 * and nlines is the number of lines to scroll. Don't redraw the old
2973 * topmost or bottommost line (where we assume current is) before
2974 * scrolling or draw the new topmost or bottommost line after scrolling
2975 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002976 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002977void edit_scroll(updown direction, int nlines)
2978{
2979 filestruct *foo;
2980 int i, scroll_rows = 0;
2981
2982 /* Scrolling less than one line or more than editwinrows lines is
2983 * redundant, so don't allow it. */
2984 if (nlines < 1 || nlines > editwinrows)
2985 return;
2986
2987 /* Move the top line of the edit window up or down (depending on the
2988 * value of direction) nlines lines. If there are fewer lines of
2989 * text than that left, move it to the top or bottom line of the
2990 * file (depending on the value of direction). Keep track of
2991 * how many lines we moved in scroll_rows. */
2992 for (i = nlines; i > 0; i--) {
2993 if (direction == UP) {
2994 if (edittop->prev == NULL)
2995 break;
2996 edittop = edittop->prev;
2997 scroll_rows--;
2998 } else {
2999 if (edittop->next == NULL)
3000 break;
3001 edittop = edittop->next;
3002 scroll_rows++;
3003 }
3004 }
3005
3006 /* Scroll the text on the screen up or down scroll_rows lines,
3007 * depending on the value of direction. */
3008 scrollok(edit, TRUE);
3009 wscrl(edit, scroll_rows);
3010 scrollok(edit, FALSE);
3011
3012 foo = edittop;
3013 if (direction != UP) {
3014 int slines = editwinrows - nlines;
3015 for (; slines > 0 && foo != NULL; slines--)
3016 foo = foo->next;
3017 }
3018
3019 /* And draw new lines on the blank top or bottom lines of the edit
3020 * window, depending on the value of direction. Don't draw the new
3021 * topmost or new bottommost line. */
3022 while (scroll_rows != 0 && foo != NULL) {
3023 if (foo->next != NULL)
3024 update_line(foo, 0);
3025 if (direction == UP)
3026 scroll_rows++;
3027 else
3028 scroll_rows--;
3029 foo = foo->next;
3030 }
3031}
3032
3033/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003034 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003035void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003036{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003037 int do_refresh = need_vertical_update(0) ||
3038 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003039 const filestruct *foo;
3040
3041 /* If either old_current or current is offscreen, refresh the screen
3042 * and get out. */
3043 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3044 edittop->lineno + editwinrows || current->lineno <
3045 edittop->lineno || current->lineno >= edittop->lineno +
3046 editwinrows) {
3047 edit_refresh();
3048 return;
3049 }
3050
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003051 /* Update old_current and current if we're not on the first page
3052 * and/or we're not on the same page as before. If the mark is on,
3053 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003054 foo = old_current;
3055 while (foo != current) {
3056 if (do_refresh)
3057 update_line(foo, 0);
3058#ifndef NANO_SMALL
3059 if (!ISSET(MARK_ISSET))
3060#endif
3061 break;
3062 if (foo->lineno > current->lineno)
3063 foo = foo->prev;
3064 else
3065 foo = foo->next;
3066 }
3067 if (do_refresh)
3068 update_line(current, current_x);
3069}
3070
Chris Allegretta6df90f52002-07-19 01:08:59 +00003071/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003072void edit_refresh(void)
3073{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003074 if (current->lineno < edittop->lineno ||
3075 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003076 /* Note that edit_update() changes edittop so that it's in range
3077 * of current. Thus, when it then calls edit_refresh(), there
3078 * is no danger of getting an infinite loop. */
3079 edit_update(
3080#ifndef NANO_SMALL
3081 ISSET(SMOOTHSCROLL) ? NONE :
3082#endif
3083 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003084 else {
3085 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003086 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003087
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003088#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003089 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003090#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003091
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003092 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003093 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003094 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003095 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003096 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003097 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003098 }
3099 while (nlines < editwinrows) {
3100 mvwaddstr(edit, nlines, 0, hblank);
3101 nlines++;
3102 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003103 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003104 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003105 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003106}
3107
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003108/* A nice generic routine to update the edit buffer. We keep current in
3109 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003110void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003111{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003112 filestruct *foo = current;
3113
Chris Allegretta6df90f52002-07-19 01:08:59 +00003114 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003115 /* If location is CENTER, we move edittop up (editwinrows / 2)
3116 * lines. This puts current at the center of the screen. If
3117 * location is NONE, we move edittop up current_y lines if
3118 * current_y is in range of the screen, 0 lines if current_y is
3119 * less than 0, or (editwinrows - 1) lines if current_y is
3120 * greater than (editwinrows - 1). This puts current at the
3121 * same place on the screen as before, or at the top or bottom
3122 * of the screen if edittop is beyond either. */
3123 int goal;
3124
3125 if (location == CENTER)
3126 goal = editwinrows / 2;
3127 else {
3128 goal = current_y;
3129
3130 /* Limit goal to (editwinrows - 1) lines maximum. */
3131 if (goal > editwinrows - 1)
3132 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003133 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003134
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003135 for (; goal > 0 && foo->prev != NULL; goal--)
3136 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003137 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003138
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003139 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003140 edit_refresh();
3141}
3142
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003143/* Ask a simple yes/no question, specified in msg, on the statusbar.
3144 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3145 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003146int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003147{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003148 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003149 const char *yesstr; /* String of yes characters accepted. */
3150 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003151 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003152
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003153 /* yesstr, nostr, and allstr are strings of any length. Each string
3154 * consists of all characters accepted as a valid character for that
3155 * value. The first value will be the one displayed in the
3156 * shortcuts. Translators: if possible, specify both the shortcuts
3157 * for your language and English. For example, in French: "OoYy"
3158 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003159 yesstr = _("Yy");
3160 nostr = _("Nn");
3161 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003162
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003163 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003164 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003165
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003166 if (COLS < 32)
3167 width = COLS / 2;
3168
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003169 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003170 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003171
Chris Allegretta6232d662002-05-12 19:52:15 +00003172 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003173 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003174 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003175
3176 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003177 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003178 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003179 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003180 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003181
Chris Allegrettadb28e962003-01-28 01:23:40 +00003182 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003183 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003184 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003185
Chris Allegrettadb28e962003-01-28 01:23:40 +00003186 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003187 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003188 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003189
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003190 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003191
3192 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003193 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003194
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003195 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003196
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003197 wrefresh(bottomwin);
3198
Chris Allegrettadb28e962003-01-28 01:23:40 +00003199 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003200 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003201 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003202#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003203 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003204#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003205
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003206 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003207
3208 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003209 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003210#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003211 /* Look, ma! We get to duplicate lots of code from
3212 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003213 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003214 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003215
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003216 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003217 wenclose(bottomwin, mouse_y, mouse_x) &&
3218 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003219 int x = mouse_x / width;
3220 /* Did we click in the first column of shortcuts, or
3221 * the second? */
3222 int y = mouse_y - editwinrows - 3;
3223 /* Did we click in the first row of shortcuts? */
3224
3225 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3226
3227 /* x = 0 means they clicked Yes or No.
3228 * y = 0 means Yes or All. */
3229 ok = -2 * x * y + x - y + 1;
3230
3231 if (ok == 2 && !all)
3232 ok = -2;
3233 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003234 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003235#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003236 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003237 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003238 else if (strchr(yesstr, kbinput) != NULL)
3239 ok = 1;
3240 else if (strchr(nostr, kbinput) != NULL)
3241 ok = 0;
3242 else if (all && strchr(allstr, kbinput) != NULL)
3243 ok = 2;
3244 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003245
Chris Allegrettadb28e962003-01-28 01:23:40 +00003246 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003247}
3248
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003249void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003250{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003251 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003252 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003253 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003254 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003255 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003256 wnoutrefresh(bottomwin);
3257 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003258 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003259 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003260 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003261 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003262 edit_refresh();
3263 /* FIXME: bottomwin needs to be refreshed too. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003264}
3265
3266void display_main_list(void)
3267{
3268 bottombars(main_list);
3269}
3270
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003271/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3272 * display the cursor position. Otherwise, we display it only if the
3273 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003274 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003275 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3276 * old_i and old_totsize. That way, we leave the current statusbar
3277 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003278void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003279{
Chris Allegrettad26ab912003-01-28 01:16:47 +00003280 const filestruct *fileptr;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003281 size_t i = 0;
3282 static size_t old_i = 0;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003283 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003284
Chris Allegrettad26ab912003-01-28 01:16:47 +00003285 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003286
3287 if (old_totsize == -1)
3288 old_totsize = totsize;
3289
Chris Allegrettad26ab912003-01-28 01:16:47 +00003290 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
3291 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003292 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003293 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003294 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003295
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003296 /* Check whether totsize is correct. Else there is a bug
3297 * somewhere. */
3298 assert(current != filebot || i == totsize);
3299
Chris Allegrettad26ab912003-01-28 01:16:47 +00003300 if (constant && ISSET(DISABLE_CURPOS)) {
3301 UNSET(DISABLE_CURPOS);
3302 old_i = i;
3303 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003304 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003305 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003306
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003307 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003308 * unconditionally; otherwise, only display the position when the
3309 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003310 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003311 size_t xpt = xplustabs() + 1;
3312 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003313 int linepct = 100 * current->lineno / totlines;
3314 int colpct = 100 * xpt / cur_len;
3315 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
3316
3317 statusbar(
3318 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3319 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003320 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003321 (unsigned long)i, totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003322 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003323 }
3324
3325 old_i = i;
3326 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003327}
3328
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003329void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003330{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003331 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003332}
3333
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003334#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003335/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003336int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003337{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003338 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003339
3340 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3341 ptr++;
3342 j++;
3343 }
3344 if (j == COLS - 5) {
3345 /* Don't wrap at the first of two spaces following a period. */
3346 if (*ptr == ' ' && *(ptr + 1) == ' ')
3347 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003348 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003349 while (*ptr != ' ' && j > 0) {
3350 ptr--;
3351 j--;
3352 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003353 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003354 if (j == 0)
3355 j = COLS - 5;
3356 }
3357 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
3358 return j;
3359}
3360
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003361/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003362void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003363{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003364 int line = 0;
3365 /* The line number in help_text of the first displayed help line.
3366 * This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003367 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003368 /* no_more means the end of the help text is shown, so don't go
3369 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003370 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003371 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003372
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003373 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003374#ifndef DISABLE_MOUSE
3375 const shortcut *oldshortcut = currshortcut;
3376 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003377 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003378#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003379
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003380 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003381 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003382 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003383 blank_statusbar();
3384
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003385 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003386 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003387 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003388
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003389#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003390 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003391 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003392 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003393#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003394
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003395 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003396 /* Make sure that the help screen's shortcut list will actually
3397 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003398 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003399 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003400 }
3401 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003402
3403 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003404 int i;
3405 int old_line = line;
3406 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003407 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003408
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003409 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003410#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003411 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003412 {
3413 int mouse_x, mouse_y;
3414 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3415 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003416 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003417#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003418 case NANO_NEXTPAGE_KEY:
3419 case NANO_NEXTPAGE_FKEY:
3420 if (!no_more)
3421 line += editwinrows - 2;
3422 break;
3423 case NANO_PREVPAGE_KEY:
3424 case NANO_PREVPAGE_FKEY:
3425 if (line > 0) {
3426 line -= editwinrows - 2;
3427 if (line < 0)
3428 line = 0;
3429 }
3430 break;
3431 case NANO_PREVLINE_KEY:
3432 if (line > 0)
3433 line--;
3434 break;
3435 case NANO_NEXTLINE_KEY:
3436 if (!no_more)
3437 line++;
3438 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003439 }
3440
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003441 if (line == old_line && kbinput != ERR)
3442 goto skip_redisplay;
3443
3444 blank_edit();
3445
3446 assert(COLS > 5);
3447
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003448 /* Calculate where in the text we should be, based on the
3449 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003450 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003451 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003452 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003453 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003454 }
3455
Chris Allegretta4640fe32003-02-10 03:10:03 +00003456 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003457 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003458
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003459 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003460 ptr += j;
3461 if (*ptr == '\n')
3462 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003463 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003464 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003465
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003466 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003467 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003468 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3469 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003470
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003471#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003472 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003473#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003474
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003475 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003476 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003477 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003478 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003479 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003480 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003481 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003482
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003483 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003484 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003485
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003486 /* The help_init() at the beginning allocated help_text. Since
3487 * help_text has now been written to the screen, we don't need it
3488 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003489 free(help_text);
3490 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003491}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003492#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003493
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003494/* Highlight the current word being replaced or spell checked. We
3495 * expect word to have tabs and control characters expanded. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003496void do_replace_highlight(int highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003497{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003498 size_t y = xplustabs();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003499 size_t word_len = strlen(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003500
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003501 y = get_page_start(y) + COLS - y;
3502 /* Now y is the number of characters we can display on this
3503 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003504
3505 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003506
Chris Allegrettafb62f732000-12-05 11:36:41 +00003507 if (highlight_flag)
3508 wattron(edit, A_REVERSE);
3509
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003510#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003511 /* This is so we can show zero-length regexes. */
3512 if (word_len == 0)
3513 waddstr(edit, " ");
3514 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003515#endif
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003516 waddnstr(edit, word, y - 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003517
3518 if (word_len > y)
3519 waddch(edit, '$');
3520 else if (word_len == y)
3521 waddch(edit, word[word_len - 1]);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003522
3523 if (highlight_flag)
3524 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003525}
3526
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003527#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003528/* Dump the passed-in file structure to stderr. */
3529void dump_buffer(const filestruct *inptr)
3530{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003531 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003532 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003533 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003534 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003535 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003536 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003537
3538 while (inptr != NULL) {
3539 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
3540 inptr = inptr->next;
3541 }
3542}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003543
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003544/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00003545void dump_buffer_reverse(void)
3546{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003547 const filestruct *fileptr = filebot;
3548
3549 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00003550 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003551 fileptr = fileptr->prev;
3552 }
3553}
3554#endif /* DEBUG */
3555
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003556#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003557#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003558#define XLCREDIT_LEN 8
3559
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00003560/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003561void do_credits(void)
3562{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003563 int crpos = 0, xlpos = 0;
3564 const char *credits[CREDIT_LEN] = {
3565 NULL, /* "The nano text editor" */
3566 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003567 VERSION,
3568 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003569 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003570 "Chris Allegretta",
3571 "Jordi Mallach",
3572 "Adam Rogoyski",
3573 "Rob Siemborski",
3574 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003575 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003576 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00003577 "Ken Tyler",
3578 "Sven Guckes",
3579 "Florian König",
3580 "Pauli Virtanen",
3581 "Daniele Medri",
3582 "Clement Laforet",
3583 "Tedi Heriyanto",
3584 "Bill Soudan",
3585 "Christian Weisgerber",
3586 "Erik Andersen",
3587 "Big Gaute",
3588 "Joshua Jensen",
3589 "Ryan Krebs",
3590 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003591 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003592 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003593 "Plattsburgh State University",
3594 "Benet Laboratories",
3595 "Amy Allegretta",
3596 "Linda Young",
3597 "Jeremy Robichaud",
3598 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003599 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003600 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003601 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003602 "Thomas Dickey",
3603 "Pavel Curtis",
3604 "Zeyd Ben-Halim",
3605 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003606 NULL, /* "and anyone else we forgot..." */
3607 NULL, /* "Thank you for using nano!" */
3608 "",
3609 "",
3610 "",
3611 "",
David Lawrence Ramsey6481c3f2004-01-09 23:06:54 +00003612 "(c) 1999-2004 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003613 "",
3614 "",
3615 "",
3616 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003617 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003618 };
3619
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003620 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003621 N_("The nano text editor"),
3622 N_("version"),
3623 N_("Brought to you by:"),
3624 N_("Special thanks to:"),
3625 N_("The Free Software Foundation"),
3626 N_("For ncurses:"),
3627 N_("and anyone else we forgot..."),
3628 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003629 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003630
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003631 curs_set(0);
3632 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003633 scrollok(edit, TRUE);
3634 blank_titlebar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003635 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003636 blank_statusbar();
3637 blank_bottombars();
3638 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003639 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003640 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003641
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003642 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
3643 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003644 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003645 if (crpos < CREDIT_LEN) {
3646 const char *what = credits[crpos];
3647 size_t start_x;
3648
3649 if (what == NULL) {
3650 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00003651 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003652 xlpos++;
3653 }
3654 start_x = COLS / 2 - strlen(what) / 2 - 1;
David Lawrence Ramseyeb711b02004-12-05 22:24:39 +00003655 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x,
3656 what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003657 }
3658 napms(700);
3659 scroll(edit);
3660 wrefresh(edit);
3661 if (wgetch(edit) != ERR)
3662 break;
3663 napms(700);
3664 scroll(edit);
3665 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003666 }
3667
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003668 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003669 nodelay(edit, FALSE);
3670 curs_set(1);
3671 display_main_list();
3672 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003673}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003674#endif