blob: 487365d7c95ca53b31782307595992fb314e326e [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 Ramsey315eb322005-11-28 19:35:29 +00005 * Copyright (C) 1999-2004 Chris Allegretta *
David Lawrence Ramsey47cfd192006-01-02 04:30:33 +00006 * Copyright (C) 2005-2006 David Lawrence Ramsey *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00007 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00009 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000010 * any later version. *
11 * *
David Lawrence Ramsey6e925cf2005-05-15 19:57:17 +000012 * This program is distributed in the hope that it will be useful, but *
13 * WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
15 * General Public License for more details. *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000016 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
David Lawrence Ramsey6e925cf2005-05-15 19:57:17 +000019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
20 * 02110-1301, USA. *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000021 * *
22 **************************************************************************/
23
David Lawrence Ramsey034b9942005-12-08 02:47:10 +000024#include "proto.h"
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000025
David Lawrence Ramsey143b8c72005-11-01 18:35:47 +000026#include <stdio.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000027#include <stdarg.h>
28#include <string.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000029#include <unistd.h>
David Lawrence Ramsey6f5de422005-10-06 05:28:37 +000030#include <errno.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000031#include <ctype.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000032
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +000033static int *key_buffer = NULL;
David Lawrence Ramsey74835712004-12-04 17:41:52 +000034 /* The default keystroke buffer,
35 * containing all the keystrokes we have
36 * at a given point. */
37static size_t key_buffer_len = 0;
38 /* The length of the default keystroke
39 * buffer. */
David Lawrence Ramseyfe7d53e2005-06-25 20:56:36 +000040static int statusblank = 0;
41 /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000042 * we call statusbar(), before we
43 * actually blank the statusbar. */
David Lawrence Ramseyea014742005-06-17 18:27:00 +000044static bool disable_cursorpos = FALSE;
45 /* Should we temporarily disable
46 * constant cursor position display? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000047
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000048/* Control character compatibility:
49 *
50 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
51 * VT100, and VT220.
52 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
53 * VT220, and VT320.
54 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
55 * VT220, and VT320.
56 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
57 * VT220, and VT320.
58 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
59 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000060 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000061 * ANSI, VT100, and VT220, and which is Backspace under VT320.
62 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000063 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000064 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
65 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000066 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000067 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000068 * on which the VT320 sequences are translated by the keypad to KEY_DC
69 * and [nothing]. We work around this conflict via the REBIND_DELETE
70 * flag: if it's not set, we assume VT320 compatibility, and if it is,
71 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
72 * Hemel for helping work this conflict out.
73 *
74 * Escape sequence compatibility:
75 *
76 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000077 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000078 * console), xterm, rxvt, and Eterm. Among these, there are several
79 * conflicts and omissions, outlined as follows:
80 *
81 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
82 * (Ctrl-I is also Tab on ANSI, which we already support.)
83 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
84 * NumLock off on Linux console; the latter is omitted. (The editing
85 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000086 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000087 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
88 * latter is omitted. (Mouse input will only work properly if the
89 * extended keypad value KEY_MOUSE is generated on mouse events
90 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000091 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000092 * omitted. (The editing keypad is more important to have working
93 * than the function keys, because the functions of the former are not
94 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000095 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000096 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000097 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000098 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +000099 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
100 * omitted. (The arrow keys, with or without modifiers, are more
101 * important to have working than the function keys, because the
102 * functions of the former are not arbitrary and the functions of the
103 * latter are.)
104 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
105 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000106 *
107 * Note that Center (5) on the numeric keypad with NumLock off can also
108 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000109
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000110#ifndef NANO_TINY
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000111/* Reset all the input routines that rely on character sequences. */
112void reset_kbinput(void)
113{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000114 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000115 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey6a836472005-08-01 19:12:05 +0000116 get_unicode_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000117}
118#endif
119
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000120/* Read in a sequence of keystrokes from win and save them in the
121 * default keystroke buffer. This should only be called when the
122 * default keystroke buffer is empty. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000123void get_key_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000124{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000125 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000126
127 /* If the keystroke buffer isn't empty, get out. */
128 if (key_buffer != NULL)
129 return;
130
131 /* Read in the first character using blocking input. */
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000132#ifndef NANO_TINY
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000133 allow_pending_sigwinch(TRUE);
134#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000135
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +0000136 /* Just before reading in the first character, display any pending
137 * screen updates. */
138 doupdate();
139
David Lawrence Ramsey6f5de422005-10-06 05:28:37 +0000140 while ((input = wgetch(win)) == ERR) {
141 /* If errno is EIO, it means that the input source that we were
142 * using is gone, so die gracefully. */
143 if (errno == EIO)
144 handle_hupterm(0);
145 }
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000146
David Lawrence Ramseyc275dc52005-03-08 17:45:36 +0000147
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000148#ifndef NANO_TINY
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000149 allow_pending_sigwinch(FALSE);
150#endif
151
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000152 /* Increment the length of the keystroke buffer, save the value of
153 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000154 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000155 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000156 key_buffer = (int *)nmalloc(sizeof(int));
157 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000158
159 /* Read in the remaining characters using non-blocking input. */
160 nodelay(win, TRUE);
161
162 while (TRUE) {
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000163#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000164 allow_pending_sigwinch(TRUE);
165#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000166
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000167 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000168
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000169 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000170 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000171 break;
172
173 /* Otherwise, increment the length of the keystroke buffer, save
174 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000175 * if the keystroke is an extended keypad value or FALSE if it
176 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000177 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000178 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
179 sizeof(int));
180 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000181
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000182#ifndef NANO_TINY
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000183 allow_pending_sigwinch(FALSE);
184#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000185 }
186
187 /* Switch back to non-blocking input. */
188 nodelay(win, FALSE);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000189
190#ifdef DEBUG
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000191 fprintf(stderr, "get_key_buffer(): key_buffer_len = %lu\n", (unsigned long)key_buffer_len);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000192#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000193}
194
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000195/* Return the length of the default keystroke buffer. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000196size_t get_key_buffer_len(void)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000197{
198 return key_buffer_len;
199}
200
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000201/* Add the contents of the keystroke buffer input to the default
202 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000203void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000204{
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000205#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000206 allow_pending_sigwinch(TRUE);
207 allow_pending_sigwinch(FALSE);
208#endif
209
210 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000211 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000212 return;
213
214 /* If adding input would put the default keystroke buffer beyond
215 * maximum capacity, only add enough of input to put it at maximum
216 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000217 if (key_buffer_len + input_len < key_buffer_len)
218 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000219
220 /* Add the length of input to the length of the default keystroke
221 * buffer, and reallocate the default keystroke buffer so that it
222 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000223 key_buffer_len += input_len;
224 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
225 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000226
227 /* If the default keystroke buffer wasn't empty before, move its
228 * beginning forward far enough so that we can add input to its
229 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000230 if (key_buffer_len > input_len)
231 memmove(key_buffer + input_len, key_buffer,
232 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000233
234 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000235 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000236}
237
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000238/* Put back the character stored in kbinput, putting it in byte range
239 * beforehand. If meta_key is TRUE, put back the Escape character after
240 * putting back kbinput. If func_key is TRUE, put back the function key
241 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000242void unget_kbinput(int kbinput, bool meta_key, bool func_key)
243{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000244 if (!func_key)
245 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000246
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000247 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000248
249 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000250 kbinput = NANO_CONTROL_3;
251 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000252 }
253}
254
255/* Try to read input_len characters from the default keystroke buffer.
256 * If the default keystroke buffer is empty and win isn't NULL, try to
257 * read in more characters from win and add them to the default
258 * keystroke buffer before doing anything else. If the default
259 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000260int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000261{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000262 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000263
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000264#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000265 allow_pending_sigwinch(TRUE);
266 allow_pending_sigwinch(FALSE);
267#endif
268
269 if (key_buffer_len == 0) {
270 if (win != NULL)
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000271 get_key_buffer(win);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000272
273 if (key_buffer_len == 0)
274 return NULL;
275 }
276
277 /* If input_len is greater than the length of the default keystroke
278 * buffer, only read the number of characters in the default
279 * keystroke buffer. */
280 if (input_len > key_buffer_len)
281 input_len = key_buffer_len;
282
283 /* Subtract input_len from the length of the default keystroke
284 * buffer, and allocate the keystroke buffer input so that it
285 * has enough room for input_len keystrokes. */
286 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000287 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000288
289 /* Copy input_len characters from the beginning of the default
290 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000291 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000292
293 /* If the default keystroke buffer is empty, mark it as such. */
294 if (key_buffer_len == 0) {
295 free(key_buffer);
296 key_buffer = NULL;
297 /* If the default keystroke buffer isn't empty, move its
David Lawrence Ramsey1c367b62005-09-04 03:29:47 +0000298 * beginning forward far enough so that the keystrokes in input are
299 * no longer at its beginning. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000300 } else {
301 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000302 sizeof(int));
303 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
304 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000305 }
306
307 return input;
308}
309
310/* Read in a single character. If it's ignored, swallow it and go on.
311 * Otherwise, try to translate it from ASCII, meta key sequences, escape
312 * sequences, and/or extended keypad values. Set meta_key to TRUE when
313 * we get a meta key sequence, and set func_key to TRUE when we get an
314 * extended keypad value. Supported extended keypad values consist of
315 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
316 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
317 * the function keypad (F1-F16), and the numeric keypad with NumLock
318 * off. Assume nodelay(win) is FALSE. */
319int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
320{
321 int kbinput;
322
323 /* Read in a character and interpret it. Continue doing this until
324 * we get a recognized value or sequence. */
325 while ((kbinput = parse_kbinput(win, meta_key, func_key
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000326#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000327 , FALSE
328#endif
329 )) == ERR);
330
331 return kbinput;
332}
333
334/* Translate ASCII characters, extended keypad values, and escape
335 * sequences into their corresponding key values. Set meta_key to TRUE
336 * when we get a meta key sequence, and set func_key to TRUE when we get
337 * a function key. Assume nodelay(win) is FALSE. */
338int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000339#ifndef NANO_TINY
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000340 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000341#endif
342 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000343
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000344{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000345 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000346 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000347
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000348#ifndef NANO_TINY
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000349 if (reset) {
350 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000351 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000352 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000353 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000354#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000355
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000356 *meta_key = FALSE;
357 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000358
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000359 /* Read in a character. */
360 while ((kbinput = get_input(win, 1)) == NULL);
361
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000362 switch (*kbinput) {
363 case ERR:
364 break;
365 case NANO_CONTROL_3:
366 /* Increment the escape counter. */
367 escapes++;
368 switch (escapes) {
369 case 1:
370 /* One escape: wait for more input. */
371 case 2:
372 /* Two escapes: wait for more input. */
373 break;
374 default:
375 /* More than two escapes: reset the escape counter
376 * and wait for more input. */
377 escapes = 0;
378 }
379 break;
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000380#if !defined(NANO_TINY) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000381 /* Since we don't change the default SIGWINCH handler when
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000382 * NANO_TINY is defined, KEY_RESIZE is never generated. Also,
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000383 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
384 case KEY_RESIZE:
385 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000386#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000387#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000388 case KEY_SHIFT_L:
389 case KEY_SHIFT_R:
390 case KEY_CONTROL_L:
391 case KEY_CONTROL_R:
392 case KEY_ALT_L:
393 case KEY_ALT_R:
394 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000395#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000396 default:
397 switch (escapes) {
398 case 0:
399 switch (*kbinput) {
400 case NANO_CONTROL_8:
401 retval = ISSET(REBIND_DELETE) ?
402 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
403 break;
404 case KEY_DOWN:
405 retval = NANO_NEXTLINE_KEY;
406 break;
407 case KEY_UP:
408 retval = NANO_PREVLINE_KEY;
409 break;
410 case KEY_LEFT:
411 retval = NANO_BACK_KEY;
412 break;
413 case KEY_RIGHT:
414 retval = NANO_FORWARD_KEY;
415 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000416#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000417 /* HP-UX 10 and 11 don't support KEY_HOME. */
418 case KEY_HOME:
419 retval = NANO_HOME_KEY;
420 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000421#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000422 case KEY_BACKSPACE:
423 retval = NANO_BACKSPACE_KEY;
424 break;
425 case KEY_DC:
426 retval = ISSET(REBIND_DELETE) ?
427 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
428 break;
429 case KEY_IC:
430 retval = NANO_INSERTFILE_KEY;
431 break;
432 case KEY_NPAGE:
433 retval = NANO_NEXTPAGE_KEY;
434 break;
435 case KEY_PPAGE:
436 retval = NANO_PREVPAGE_KEY;
437 break;
438 case KEY_ENTER:
439 retval = NANO_ENTER_KEY;
440 break;
441 case KEY_A1: /* Home (7) on numeric keypad
442 * with NumLock off. */
443 retval = NANO_HOME_KEY;
444 break;
445 case KEY_A3: /* PageUp (9) on numeric keypad
446 * with NumLock off. */
447 retval = NANO_PREVPAGE_KEY;
448 break;
449 case KEY_B2: /* Center (5) on numeric keypad
450 * with NumLock off. */
451 break;
452 case KEY_C1: /* End (1) on numeric keypad
453 * with NumLock off. */
454 retval = NANO_END_KEY;
455 break;
456 case KEY_C3: /* PageDown (4) on numeric
457 * keypad with NumLock off. */
458 retval = NANO_NEXTPAGE_KEY;
459 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000460#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000461 /* Slang doesn't support KEY_BEG. */
462 case KEY_BEG: /* Center (5) on numeric keypad
463 * with NumLock off. */
464 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000465#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000466#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000467 /* HP-UX 10 and 11 don't support KEY_END. */
468 case KEY_END:
469 retval = NANO_END_KEY;
470 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000471#endif
David Lawrence Ramsey475c4022006-01-30 01:32:41 +0000472#ifdef KEY_SBEG
473 /* Slang doesn't support KEY_SBEG. */
474 case KEY_SBEG: /* Center (5) on numeric keypad
475 * with NumLock off. */
476 break;
477#endif
478#ifdef KEY_SDC
479 /* Slang doesn't support KEY_SDC. */
480 case KEY_SDC:
481 retval = NANO_DELETE_KEY;
482 break;
483#endif
484#ifdef KEY_SEND
485 /* HP-UX 10 and 11 don't support KEY_SEND. */
486 case KEY_SEND:
487 retval = NANO_END_KEY;
488 break;
489#endif
490#ifdef KEY_SHOME
491 /* HP-UX 10 and 11 and Slang don't support
492 * KEY_SHOME. */
493 case KEY_SHOME:
494 retval = NANO_HOME_KEY;
495 break;
496#endif
497#ifdef KEY_SIC
498 /* Slang doesn't support KEY_SIC. */
499 case KEY_SIC:
500 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000501 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000502#endif
503#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000504 /* Slang doesn't support KEY_SLEFT. */
505 case KEY_SLEFT:
506 retval = NANO_BACK_KEY;
507 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000508#endif
509#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000510 /* Slang doesn't support KEY_SRIGHT. */
511 case KEY_SRIGHT:
512 retval = NANO_FORWARD_KEY;
513 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000514#endif
David Lawrence Ramsey475c4022006-01-30 01:32:41 +0000515#ifdef KEY_SSUSPEND
516 /* Slang doesn't support KEY_SSUSPEND. */
517 case KEY_SSUSPEND:
518 retval = NANO_SUSPEND_KEY;
519 break;
520#endif
521#ifdef KEY_SUSPEND
522 /* Slang doesn't support KEY_SUSPEND. */
523 case KEY_SUSPEND:
524 retval = NANO_SUSPEND_KEY;
525 break;
526#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000527 default:
528 retval = *kbinput;
529 break;
530 }
531 break;
532 case 1:
533 /* One escape followed by a non-escape: escape
534 * sequence mode. Reset the escape counter. If
535 * there aren't any other keys waiting, we have a
536 * meta key sequence, so set meta_key to TRUE and
537 * save the lowercase version of the non-escape
538 * character as the result. If there are other keys
539 * waiting, we have a true escape sequence, so
540 * interpret it. */
541 escapes = 0;
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000542 if (get_key_buffer_len() == 0) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000543 *meta_key = TRUE;
544 retval = tolower(*kbinput);
545 } else {
546 int *seq;
547 size_t seq_len;
548 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000549
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000550 /* Put back the non-escape character, get the
551 * complete escape sequence, translate the
552 * sequence into its corresponding key value,
553 * and save that as the result. */
554 unget_input(kbinput, 1);
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000555 seq_len = get_key_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000556 seq = get_input(NULL, seq_len);
557 retval = get_escape_seq_kbinput(seq, seq_len,
558 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000559
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000560 /* If the escape sequence is unrecognized and
561 * not ignored, put back all of its characters
562 * except for the initial escape. */
563 if (retval == ERR && !ignore_seq)
564 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000565
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000566 free(seq);
567 }
568 break;
569 case 2:
570 /* Two escapes followed by one or more decimal
David Lawrence Ramsey38f70a52005-07-19 18:46:02 +0000571 * digits: byte sequence mode. If the byte
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000572 * sequence's range is limited to 2XX (the first
573 * digit is in the '0' to '2' range and it's the
574 * first digit, or it's in the '0' to '9' range and
575 * it's not the first digit), increment the byte
576 * sequence counter and interpret the digit. If the
577 * byte sequence's range is not limited to 2XX, fall
578 * through. */
579 if (('0' <= *kbinput && *kbinput <= '6' &&
580 byte_digits == 0) || ('0' <= *kbinput &&
581 *kbinput <= '9' && byte_digits > 0)) {
582 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000583
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000584 byte_digits++;
585 byte = get_byte_kbinput(*kbinput
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000586#ifndef NANO_TINY
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000587 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000588#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000589 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000590
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000591 if (byte != ERR) {
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000592 char *byte_mb;
593 int byte_mb_len, *seq, i;
594
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000595 /* If we've read in a complete byte
596 * sequence, reset the byte sequence counter
597 * and the escape counter, and put back the
598 * corresponding byte value. */
599 byte_digits = 0;
600 escapes = 0;
601
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000602 /* Put back the multibyte equivalent of the
603 * byte value. */
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +0000604 byte_mb = make_mbchar((long)byte,
605 &byte_mb_len);
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000606
607 seq = (int *)nmalloc(byte_mb_len *
608 sizeof(int));
609
610 for (i = 0; i < byte_mb_len; i++)
611 seq[i] = (unsigned char)byte_mb[i];
612
613 unget_input(seq, byte_mb_len);
614
615 free(byte_mb);
616 free(seq);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000617 }
618 } else {
619 /* Reset the escape counter. */
620 escapes = 0;
621 if (byte_digits == 0)
622 /* Two escapes followed by a non-decimal
623 * digit or a decimal digit that would
624 * create a byte sequence greater than 2XX,
625 * and we're not in the middle of a byte
626 * sequence: control character sequence
627 * mode. Interpret the control sequence and
628 * save the corresponding control character
629 * as the result. */
630 retval = get_control_kbinput(*kbinput);
631 else {
632 /* If we're in the middle of a byte
633 * sequence, reset the byte sequence counter
634 * and save the character we got as the
635 * result. */
636 byte_digits = 0;
637 retval = *kbinput;
638 }
639 }
640 break;
641 }
642 }
643
644 /* If we have a result and it's an extended keypad value (i.e, a
645 * value outside of byte range), set func_key to TRUE. */
646 if (retval != ERR)
647 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000648
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000649#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000650 fprintf(stderr, "parse_kbinput(): kbinput = %d, meta_key = %d, func_key = %d, escapes = %d, byte_digits = %d, retval = %d\n", *kbinput, (int)*meta_key, (int)*func_key, escapes, byte_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000651#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000652
653 /* Return the result. */
654 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000655}
656
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000657/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000658 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000659 * are generated when the keypad doesn't support the needed keys. If
660 * the escape sequence is recognized but we want to ignore it, return
661 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
662 * set ignore_seq to FALSE. Assume that Escape has already been read
663 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000664int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000665 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000666{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000667 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000668
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000669 *ignore_seq = FALSE;
670
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000671 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000672 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000673 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000674 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000675 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000676 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000677 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000678 case 'P': /* Esc O 2 P == F13 on
679 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000680 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000681 break;
682 case 'Q': /* Esc O 2 Q == F14 on
683 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000684 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000685 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000686 case 'R': /* Esc O 2 R == F15 on
687 * xterm. */
688 retval = KEY_F(15);
689 break;
690 case 'S': /* Esc O 2 S == F16 on
691 * xterm. */
692 retval = KEY_F(16);
693 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000694 }
695 }
696 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000697 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
698 case 'B': /* Esc O B == Down on
699 * VT100/VT320/xterm. */
700 case 'C': /* Esc O C == Right on
701 * VT100/VT320/xterm. */
702 case 'D': /* Esc O D == Left on
703 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000704 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000705 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000706 case 'E': /* Esc O E == Center (5) on numeric keypad
707 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000708 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000709 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000710 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000711 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000712 break;
713 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000714 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000715 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000716 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000717 * NumLock off on VT100/VT220/VT320/xterm/
718 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000719 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000720 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000721 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000722 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000723 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000724 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000725 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000726 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000727 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000728 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000729 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000730 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000731 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000732 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000733 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000734 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000735 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000736 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000737 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000738 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000739 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000740 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000741 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000742 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000743 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000744 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000745 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000746 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000747 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000748 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000749 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000750 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000751 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000752 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000753 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000754 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000755 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000756 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000757 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000758 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000759 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000760 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000761 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000762 * NumLock off on VT100/VT220/VT320/xterm/
763 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000764 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000765 break;
766 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000767 * NumLock off on VT100/VT220/VT320/xterm/
768 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000769 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000770 break;
771 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000772 * NumLock off on VT100/VT220/VT320/xterm/
773 * rxvt. */
David Lawrence Ramsey8f36d092005-09-24 19:42:48 +0000774 retval = ',';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000775 break;
776 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000777 * NumLock off on VT100/VT220/VT320/xterm/
778 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000779 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000780 break;
781 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000782 * with NumLock off on VT100/VT220/VT320/
783 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000784 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000785 break;
786 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000787 * NumLock off on VT100/VT220/VT320/xterm/
788 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000789 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000790 break;
791 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000792 * with NumLock off on VT100/VT220/VT320/
793 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000794 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000795 break;
796 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000797 * with NumLock off on VT100/VT220/VT320/
798 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000799 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000800 break;
801 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000802 * with NumLock off on VT100/VT220/VT320/
803 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000804 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000805 break;
806 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000807 * keypad with NumLock off on VT100/VT220/
808 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000809 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000810 break;
811 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000812 * with NumLock off on VT100/VT220/VT320/
813 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000814 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000815 break;
816 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000817 * with NumLock off on VT100/VT220/VT320/
818 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000819 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000820 break;
821 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000822 * with NumLock off on VT100/VT220/VT320/
823 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000824 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000825 break;
826 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000827 * with NumLock off on VT100/VT220/VT320/
828 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000829 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000830 break;
831 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000832 * with NumLock off on VT100/VT220/VT320/
833 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000834 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000835 break;
836 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000837 * with NumLock off on VT100/VT220/VT320/
838 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000839 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000840 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000841 }
842 break;
843 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000844 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000845 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000846 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000847 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000848 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000849 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000850 break;
851 }
852 break;
853 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000854 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000855 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000856 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000857 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000858 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
859 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000860 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000861 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000862 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
863 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000864 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000865 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000866 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
867 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000868 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000869 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000870 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
871 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000872 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000873 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000874 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
875 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000876 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000877 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000878 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000879 * VT220/VT320/Linux console/
880 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000881 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000882 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000883 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000884 * VT220/VT320/Linux console/
885 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000886 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000887 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000888 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000889 * VT220/VT320/Linux console/
890 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000891 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000892 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000893 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000894 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000895 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000896 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000897 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000898 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000899 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
900 * xterm. */
901 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
902 * xterm. */
903 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
904 * xterm. */
905 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
906 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000907 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000908 break;
909 }
910 }
911 break;
912 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000913 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000914 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000915 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
916 * xterm. */
917 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
918 * xterm. */
919 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
920 * xterm. */
921 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
922 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000923 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000924 break;
925 }
926 }
927 break;
928 }
929 }
930 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000931 default: /* Esc [ 1 ~ == Home on
932 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000933 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000934 break;
935 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000936 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000937 break;
938 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000939 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000940 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000941 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000942 * VT220/VT320/Linux console/
943 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000944 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000945 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000946 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000947 * VT220/VT320/Linux console/
948 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000949 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000950 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000951 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000952 * VT220/VT320/Linux console/
953 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000954 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000955 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000956 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000957 * VT220/VT320/Linux console/
958 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000959 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000960 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000961 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000962 * VT220/VT320/Linux console/
963 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000964 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000965 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000966 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000967 * VT220/VT320/Linux console/
968 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000969 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000970 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000971 case '8': /* Esc [ 2 8 ~ == F15 on
972 * VT220/VT320/Linux console/
973 * rxvt/Eterm. */
974 retval = KEY_F(15);
975 break;
976 case '9': /* Esc [ 2 9 ~ == F16 on
977 * VT220/VT320/Linux console/
978 * rxvt/Eterm. */
979 retval = KEY_F(16);
980 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000981 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000982 * VT220/VT320/Linux console/
983 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000984 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000985 break;
986 }
987 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000988 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000989 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
990 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000991 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000992 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000993 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000994 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000995 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000996 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000997 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
998 * Linux console/xterm; Esc [ 5 ^ ==
999 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001000 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001001 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001002 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
1003 * Linux console/xterm; Esc [ 6 ^ ==
1004 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001005 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001006 break;
1007 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001008 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001009 break;
1010 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001011 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001012 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001013 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001014 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001015 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001016 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001017 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001018 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001019 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001020 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001021 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001022 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001023 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001024 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001025 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001026 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001027 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001028 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001029 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001030 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001031 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001032 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001033 case 'E': /* Esc [ E == Center (5) on numeric keypad
1034 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +00001035 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001036 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001037 case 'F': /* Esc [ F == End on FreeBSD
1038 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001039 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001040 break;
1041 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001042 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001043 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001044 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001045 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001046 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001047 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001048 break;
1049 case 'I': /* Esc [ I == PageUp on FreeBSD
1050 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001051 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001052 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001053 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001054 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001055 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001056 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001057 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001058 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001059 break;
1060 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001062 break;
1063 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001064 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001065 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001066 case 'P': /* Esc [ O P == F1 on
1067 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001068 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001069 break;
1070 case 'Q': /* Esc [ O Q == F2 on
1071 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001072 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001073 break;
1074 case 'R': /* Esc [ O R == F3 on
1075 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001076 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001077 break;
1078 case 'S': /* Esc [ O S == F4 on
1079 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001080 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001081 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001082 }
David Lawrence Ramseyec729752005-09-25 18:42:05 +00001083 } else
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001084 /* Esc [ O == F3 on FreeBSD console. */
1085 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001086 break;
1087 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001088 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001089 break;
1090 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001091 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001092 break;
1093 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001094 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001095 break;
1096 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001097 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001098 break;
1099 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001100 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001101 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001102 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001103 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001104 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001105 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001106 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001107 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001108 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001109 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001110 break;
1111 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001112 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001113 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001114 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001115 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001116 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001117 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001118 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001119 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001120 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001121 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001122 case 'c': /* Esc [ c == Shift-Right on rxvt/
1123 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001124 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001125 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001126 break;
1127 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001128 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001129 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001130 case 'A': /* Esc [ [ A == F1 on Linux
1131 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001132 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001133 break;
1134 case 'B': /* Esc [ [ B == F2 on Linux
1135 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001136 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001137 break;
1138 case 'C': /* Esc [ [ C == F3 on Linux
1139 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001140 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001141 break;
1142 case 'D': /* Esc [ [ D == F4 on Linux
1143 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001144 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001145 break;
1146 case 'E': /* Esc [ [ E == F5 on Linux
1147 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001148 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001149 break;
1150 }
1151 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001152 break;
1153 }
1154 break;
1155 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001156 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001157
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001158#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001159 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001160#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001161
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001162 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001163}
1164
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001165/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001166 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001167 * to many escape sequences. */
1168int get_escape_seq_abcd(int kbinput)
1169{
1170 switch (tolower(kbinput)) {
1171 case 'a':
1172 return NANO_PREVLINE_KEY;
1173 case 'b':
1174 return NANO_NEXTLINE_KEY;
1175 case 'c':
1176 return NANO_FORWARD_KEY;
1177 case 'd':
1178 return NANO_BACK_KEY;
1179 default:
1180 return ERR;
1181 }
1182}
1183
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001184/* Translate a byte sequence: turn a three-digit decimal number from
1185 * 000 to 255 into its corresponding byte value. */
1186int get_byte_kbinput(int kbinput
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001187#ifndef NANO_TINY
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001188 , bool reset
1189#endif
1190 )
1191{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001192 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001193 int retval = ERR;
1194
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001195#ifndef NANO_TINY
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001196 if (reset) {
1197 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001198 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001199 return ERR;
1200 }
1201#endif
1202
1203 /* Increment the byte digit counter. */
1204 byte_digits++;
1205
1206 switch (byte_digits) {
1207 case 1:
1208 /* One digit: reset the byte sequence holder and add the
1209 * digit we got to the 100's position of the byte sequence
1210 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001211 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001212 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001213 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001214 else
1215 /* If the character we got isn't a decimal digit, or if
1216 * it is and it would put the byte sequence out of byte
1217 * range, save it as the result. */
1218 retval = kbinput;
1219 break;
1220 case 2:
1221 /* Two digits: add the digit we got to the 10's position of
1222 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001223 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1224 '6' <= kbinput && kbinput <= '9'))
1225 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001226 else
1227 /* If the character we got isn't a decimal digit, or if
1228 * it is and it would put the byte sequence out of byte
1229 * range, save it as the result. */
1230 retval = kbinput;
1231 break;
1232 case 3:
1233 /* Three digits: add the digit we got to the 1's position of
1234 * the byte sequence holder, and save the corresponding word
1235 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001236 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1237 '6' <= kbinput && kbinput <= '9')) {
1238 byte += (kbinput - '0');
1239 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001240 } else
1241 /* If the character we got isn't a decimal digit, or if
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001242 * it is and it would put the byte sequence out of word
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001243 * range, save it as the result. */
1244 retval = kbinput;
1245 break;
1246 default:
1247 /* More than three digits: save the character we got as the
1248 * result. */
1249 retval = kbinput;
1250 break;
1251 }
1252
1253 /* If we have a result, reset the byte digit counter and the byte
1254 * sequence holder. */
1255 if (retval != ERR) {
1256 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001257 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001258 }
1259
1260#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001261 fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte = %d, retval = %d\n", kbinput, byte_digits, byte, retval);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001262#endif
1263
1264 return retval;
1265}
1266
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001267/* Translate a Unicode sequence: turn a six-digit hexadecimal number
1268 * from 000000 to 10FFFF (case-insensitive) into its corresponding
1269 * multibyte value. */
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001270long get_unicode_kbinput(int kbinput
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001271#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001272 , bool reset
1273#endif
1274 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001275{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001276 static int uni_digits = 0;
1277 static long uni = 0;
1278 long retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001279
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001280#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001281 if (reset) {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001282 uni_digits = 0;
1283 uni = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001284 return ERR;
1285 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001286#endif
1287
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001288 /* Increment the Unicode digit counter. */
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001289 uni_digits++;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001290
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001291 switch (uni_digits) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001292 case 1:
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001293 /* One digit: reset the Unicode sequence holder and add the
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001294 * digit we got to the 0x100000's position of the Unicode
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001295 * sequence holder. */
1296 uni = 0;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001297 if ('0' <= kbinput && kbinput <= '1')
1298 uni += (kbinput - '0') * 0x100000;
1299 else
1300 /* If the character we got isn't a hexadecimal digit, or
1301 * if it is and it would put the Unicode sequence out of
1302 * valid range, save it as the result. */
1303 retval = kbinput;
1304 break;
1305 case 2:
1306 /* Two digits: add the digit we got to the 0x10000's
1307 * position of the Unicode sequence holder. */
1308 if ('0' == kbinput || (uni < 0x100000 && '1' <= kbinput &&
1309 kbinput <= '9'))
1310 uni += (kbinput - '0') * 0x10000;
1311 else if (uni < 0x100000 && 'a' <= tolower(kbinput) &&
1312 tolower(kbinput) <= 'f')
1313 uni += (tolower(kbinput) + 10 - 'a') * 0x10000;
1314 else
1315 /* If the character we got isn't a hexadecimal digit, or
1316 * if it is and it would put the Unicode sequence out of
1317 * valid range, save it as the result. */
1318 retval = kbinput;
1319 break;
1320 case 3:
1321 /* Three digits: add the digit we got to the 0x1000's
1322 * position of the Unicode sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001323 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001324 uni += (kbinput - '0') * 0x1000;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001325 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001326 uni += (tolower(kbinput) + 10 - 'a') * 0x1000;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001327 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001328 /* If the character we got isn't a hexadecimal digit, or
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001329 * if it is and it would put the Unicode sequence out of
1330 * valid range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001331 retval = kbinput;
1332 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001333 case 4:
1334 /* Four digits: add the digit we got to the 0x100's position
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001335 * of the Unicode sequence holder. */
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001336 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001337 uni += (kbinput - '0') * 0x100;
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001338 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001339 uni += (tolower(kbinput) + 10 - 'a') * 0x100;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001340 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001341 /* If the character we got isn't a hexadecimal digit, or
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001342 * if it is and it would put the Unicode sequence out of
1343 * valid range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001344 retval = kbinput;
1345 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001346 case 5:
1347 /* Five digits: add the digit we got to the 0x10's position
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001348 * of the Unicode sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001349 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001350 uni += (kbinput - '0') * 0x10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001351 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001352 uni += (tolower(kbinput) + 10 - 'a') * 0x10;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001353 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001354 /* If the character we got isn't a hexadecimal digit, or
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001355 * if it is and it would put the Unicode sequence out of
1356 * valid range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001357 retval = kbinput;
1358 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001359 case 6:
1360 /* Six digits: add the digit we got to the 1's position of
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001361 * the Unicode sequence holder, and save the corresponding
1362 * Unicode value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001363 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001364 uni += (kbinput - '0');
1365 retval = uni;
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001366 } else if ('a' <= tolower(kbinput) && tolower(kbinput) <=
1367 'f') {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001368 uni += (tolower(kbinput) + 10 - 'a');
1369 retval = uni;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001370 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001371 /* If the character we got isn't a hexadecimal digit, or
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001372 * if it is and it would put the Unicode sequence out of
1373 * valid range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001374 retval = kbinput;
1375 break;
1376 default:
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001377 /* More than six digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001378 * result. */
1379 retval = kbinput;
1380 break;
1381 }
1382
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001383 /* If we have a result, reset the Unicode digit counter and the
1384 * Unicode sequence holder. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001385 if (retval != ERR) {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001386 uni_digits = 0;
1387 uni = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001388 }
1389
1390#ifdef DEBUG
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001391 fprintf(stderr, "get_unicode_kbinput(): kbinput = %d, uni_digits = %d, uni = %ld, retval = %ld\n", kbinput, uni_digits, uni, retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001392#endif
1393
1394 return retval;
1395}
1396
1397/* Translate a control character sequence: turn an ASCII non-control
1398 * character into its corresponding control character. */
1399int get_control_kbinput(int kbinput)
1400{
1401 int retval;
1402
1403 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1404 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1405 kbinput == '`')
1406 retval = NANO_CONTROL_SPACE;
1407 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1408 else if ('3' <= kbinput && kbinput <= '7')
1409 retval = kbinput - 24;
1410 /* Ctrl-8 (Ctrl-?) */
1411 else if (kbinput == '8' || kbinput == '?')
1412 retval = NANO_CONTROL_8;
1413 /* Ctrl-A to Ctrl-_ */
1414 else if ('A' <= kbinput && kbinput <= '_')
1415 retval = kbinput - 64;
1416 /* Ctrl-a to Ctrl-~ */
1417 else if ('a' <= kbinput && kbinput <= '~')
1418 retval = kbinput - 96;
1419 else
1420 retval = kbinput;
1421
1422#ifdef DEBUG
1423 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1424#endif
1425
1426 return retval;
1427}
1428
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001429/* Put the output-formatted characters in output back into the default
1430 * keystroke buffer, so that they can be parsed and displayed as output
1431 * again. */
1432void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001433{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001434 int *input;
1435 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001436
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001437 if (output_len == 0)
1438 return;
1439
1440 input = (int *)nmalloc(output_len * sizeof(int));
1441 for (i = 0; i < output_len; i++)
1442 input[i] = (int)output[i];
1443 unget_input(input, output_len);
1444 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001445}
1446
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001447/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001448 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1449int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1450{
1451 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001452
1453 /* Turn off flow control characters if necessary so that we can type
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001454 * them in verbatim, and turn the keypad off if necessary so that we
1455 * don't get extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001456 if (ISSET(PRESERVE))
1457 disable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001458 if (!ISSET(REBIND_KEYPAD))
1459 keypad(win, FALSE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001460
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001461 /* Read in a stream of characters and interpret it if possible. */
1462 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001463
1464 /* Turn flow control characters back on if necessary and turn the
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001465 * keypad back on if necessary now that we're done. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001466 if (ISSET(PRESERVE))
1467 enable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001468 if (!ISSET(REBIND_KEYPAD))
1469 keypad(win, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001470
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001471 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001472}
1473
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001474/* Read in a stream of all available characters, and return the length
1475 * of the string in kbinput_len. Translate the first few characters of
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001476 * the input into the corresponding multibyte value if possible. After
1477 * that, leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001478int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001479{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001480 int *kbinput, *retval;
1481 long uni;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001482
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001483 /* Read in the first keystroke. */
1484 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001485
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001486 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001487 uni = get_unicode_kbinput(*kbinput
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001488#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001489 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001490#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001491 );
1492
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001493 /* If the first keystroke isn't a hexadecimal digit, put back the
1494 * first keystroke. */
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001495 if (uni != ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001496 unget_input(kbinput, 1);
1497 /* Otherwise, read in keystrokes until we have a complete word
1498 * sequence, and put back the corresponding word value. */
1499 else {
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001500 char *uni_mb;
1501 int uni_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001502
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001503 while (uni == ERR) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001504 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001505
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001506 uni = get_unicode_kbinput(*kbinput
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001507#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001508 , FALSE
1509#endif
1510 );
1511 }
1512
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001513 /* Put back the multibyte equivalent of the Unicode value. */
1514 uni_mb = make_mbchar(uni, &uni_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001515
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001516 seq = (int *)nmalloc(uni_mb_len * sizeof(int));
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001517
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001518 for (i = 0; i < uni_mb_len; i++)
1519 seq[i] = (unsigned char)uni_mb[i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001520
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001521 unget_input(seq, uni_mb_len);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001522
1523 free(seq);
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001524 free(uni_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001525 }
1526
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001527 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001528 * result. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00001529 *kbinput_len = get_key_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001530 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001531
1532 return retval;
1533}
1534
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001535#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001536/* Check for a mouse event, and if one's taken place, save the
1537 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001538 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1539 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001540 * place on it, figure out which shortcut was clicked and put back the
1541 * equivalent keystroke(s). Return FALSE if no keystrokes were
1542 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001543 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001544bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001545{
1546 MEVENT mevent;
1547
1548 *mouse_x = -1;
1549 *mouse_y = -1;
1550
1551 /* First, get the actual mouse event. */
1552 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001553 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001554
1555 /* Save the screen coordinates where the mouse event took place. */
1556 *mouse_x = mevent.x;
1557 *mouse_y = mevent.y;
1558
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001559 /* If we're allowing shortcuts, the current shortcut list is being
1560 * displayed on the last two lines of the screen, and the mouse
1561 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001562 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001563 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1564 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001565 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001566 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001567 /* The number of shortcuts in the current shortcut list. */
1568 const shortcut *s = currshortcut;
1569 /* The actual shortcut we clicked on, starting at the first
1570 * one in the current shortcut list. */
1571
1572 /* Get the shortcut lists' length. */
1573 if (currshortcut == main_list)
1574 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001575 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001576 currslen = length_of_list(currshortcut);
1577
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001578 /* We don't show any more shortcuts than the main list
1579 * does. */
1580 if (currslen > MAIN_VISIBLE)
1581 currslen = MAIN_VISIBLE;
1582 }
1583
David Lawrence Ramsey0df61f12005-06-08 20:23:06 +00001584 /* Calculate the width of each shortcut in the list. It's the
1585 * same for all of them. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001586 if (currslen < 2)
1587 i = COLS / 6;
1588 else
1589 i = COLS / ((currslen / 2) + (currslen % 2));
1590
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001591 /* Calculate the y-coordinate relative to the beginning of
David Lawrence Ramseyf7260532005-10-28 17:12:58 +00001592 * the shortcut list in bottomwin, i.e, with the sizes of
1593 * topwin, edit, and the first line of bottomwin subtracted
1594 * out. */
1595 j = *mouse_y - (2 - no_more_space()) - editwinrows - 1;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001596
1597 /* If we're on the statusbar, beyond the end of the shortcut
1598 * list, or beyond the end of a shortcut on the right side of
1599 * the screen, don't do anything. */
1600 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001601 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001602 j = (*mouse_x / i) * 2 + j;
1603 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001604 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001605
1606 /* Go through the shortcut list to determine which shortcut was
1607 * clicked. */
1608 for (; j > 0; j--)
1609 s = s->next;
1610
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001611 /* And put back the equivalent key. Assume that each shortcut
1612 * has, at the very least, an equivalent control key, an
1613 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001614 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001615 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001616 return TRUE;
1617 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001618 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001619 return TRUE;
1620 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001621 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001622 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001623}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001624#endif /* !DISABLE_MOUSE */
1625
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001626/* Return the shortcut corresponding to the values of kbinput (the key
1627 * itself), meta_key (whether the key is a meta sequence), and func_key
1628 * (whether the key is a function key), if any. The shortcut will be
1629 * the first one in the list (control key, meta key sequence, function
1630 * key, other meta key sequence) for the corresponding function. For
1631 * example, passing in a meta key sequence that corresponds to a
1632 * function with a control key, a function key, and a meta key sequence
1633 * will return the control key corresponding to that function. */
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001634const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001635 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001636{
1637 const shortcut *s = s_list;
1638 size_t slen = length_of_list(s_list);
1639
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001640#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001641 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 +00001642#endif
1643
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001644 /* Check for shortcuts. */
1645 for (; slen > 0; slen--) {
1646 /* We've found a shortcut if:
1647 *
1648 * 1. The key exists.
1649 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001650 * 3. meta_key is TRUE and the key is the primary or
1651 * miscellaneous meta sequence in the shortcut list.
1652 * 4. func_key is TRUE and the key is a function key in the
1653 * shortcut list. */
1654
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001655 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1656 (*meta_key == TRUE && (*kbinput == s->metaval ||
1657 *kbinput == s->miscval)) || (*func_key == TRUE &&
1658 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001659 break;
1660 }
1661
1662 s = s->next;
1663 }
1664
1665 /* Translate the shortcut to either its control key or its meta key
1666 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001667 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001668 if (slen > 0) {
1669 if (s->ctrlval != NANO_NO_KEY) {
1670 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001671 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001672 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001673 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001674 } else if (s->metaval != NANO_NO_KEY) {
1675 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001676 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001677 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001678 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001679 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001680 }
1681
1682 return NULL;
1683}
1684
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001685#ifndef NANO_TINY
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001686/* Return the global toggle corresponding to the values of kbinput (the
1687 * key itself) and meta_key (whether the key is a meta sequence), if
1688 * any. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001689const toggle *get_toggle(int kbinput, bool meta_key)
1690{
1691 const toggle *t = toggles;
1692
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001693#ifdef DEBUG
1694 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1695#endif
1696
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001697 /* Check for toggles. */
1698 for (; t != NULL; t = t->next) {
1699 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001700 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001701 if (meta_key && kbinput == t->val)
1702 break;
1703 }
1704
1705 return t;
1706}
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001707#endif /* !NANO_TINY */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001708
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001709/* Move to (x, y) in win, and display a line of n spaces with the
1710 * current attributes. */
1711void blank_line(WINDOW *win, int y, int x, int n)
1712{
1713 wmove(win, y, x);
1714 for (; n > 0; n--)
1715 waddch(win, ' ');
1716}
1717
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001718/* Blank the first line of the top portion of the window. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001719void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001720{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001721 blank_line(topwin, 0, 0, COLS);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001722}
1723
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001724/* If the MORE_SPACE flag isn't set, blank the second line of the top
1725 * portion of the window. */
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00001726void blank_topbar(void)
1727{
1728 if (!ISSET(MORE_SPACE))
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001729 blank_line(topwin, 1, 0, COLS);
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00001730}
1731
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001732/* Blank all the lines of the middle portion of the window, i.e, the
1733 * edit window. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001734void blank_edit(void)
1735{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001736 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001737 for (i = 0; i < editwinrows; i++)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001738 blank_line(edit, i, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001739}
1740
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001741/* Blank the first line of the bottom portion of the window. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001742void blank_statusbar(void)
1743{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001744 blank_line(bottomwin, 0, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001745}
1746
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001747/* If the NO_HELP flag isn't set, blank the last two lines of the bottom
1748 * portion of the window. */
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00001749void blank_bottombars(void)
1750{
1751 if (!ISSET(NO_HELP)) {
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001752 blank_line(bottomwin, 1, 0, COLS);
1753 blank_line(bottomwin, 2, 0, COLS);
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00001754 }
1755}
1756
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001757/* Check if the number of keystrokes needed to blank the statusbar has
1758 * been pressed. If so, blank the statusbar, unless constant cursor
1759 * position display is on. */
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001760void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001761{
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00001762 if (statusblank > 0)
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001763 statusblank--;
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00001764
1765 if (statusblank == 0 && !ISSET(CONST_UPDATE)) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001766 blank_statusbar();
1767 wnoutrefresh(bottomwin);
1768 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00001769 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001770 }
1771}
1772
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001773/* Convert buf into a string that can be displayed on screen. The
1774 * caller wants to display buf starting with column start_col, and
1775 * extending for at most len columns. start_col is zero-based. len is
1776 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001777 * string is dynamically allocated, and should be freed. If dollars is
1778 * TRUE, the caller might put "$" at the beginning or end of the line if
1779 * it's too long. */
1780char *display_string(const char *buf, size_t start_col, size_t len, bool
1781 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001782{
1783 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00001784 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001785 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00001786 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001787 size_t alloc_len;
1788 /* The length of memory allocated for converted. */
1789 char *converted;
1790 /* The string we return. */
1791 size_t index;
1792 /* Current position in converted. */
1793
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001794 char *buf_mb = charalloc(mb_cur_max());
1795 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001796
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00001797 /* If dollars is TRUE, make room for the "$" at the end of the
1798 * line. */
1799 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
1800 len--;
1801
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001802 if (len == 0)
1803 return mallocstrcpy(NULL, "");
1804
1805 start_index = actual_x(buf, start_col);
1806 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001807
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001808 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001809
David Lawrence Ramseyc4b854d2005-09-20 04:15:33 +00001810 /* Allocate enough space for the entire line. */
David Lawrence Ramsey86b6c3e2005-10-04 03:40:41 +00001811 alloc_len = (mb_cur_max() * (COLS + 1));
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00001812
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001813 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001814 index = 0;
1815
David Lawrence Ramsey7f26c732005-09-05 01:36:47 +00001816 if (buf[start_index] != '\t' && (column < start_col || (dollars &&
1817 column > 0))) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001818 /* We don't display all of buf[start_index] since it starts to
1819 * the left of the screen. */
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001820 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001821
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001822 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00001823 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001824 char *ctrl_buf_mb = charalloc(mb_cur_max());
1825 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001826
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001827 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
1828 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00001829
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001830 for (i = 0; i < ctrl_buf_mb_len; i++)
1831 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001832
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001833 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001834
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001835 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00001836
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001837 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001838 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00001839 }
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00001840#ifdef ENABLE_UTF8
David Lawrence Ramsey7a4aaa52005-06-16 02:09:57 +00001841 else if (ISSET(USE_UTF8) && mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00001842 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00001843 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001844
1845 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001846 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00001847#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001848 }
1849
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00001850 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001851 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001852
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00001853 /* If buf contains a tab character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001854 if (*buf_mb == '\t') {
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001855#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001856 if (ISSET(WHITESPACE_DISPLAY)) {
1857 int i;
1858
1859 for (i = 0; i < whitespace_len[0]; i++)
1860 converted[index++] = whitespace[i];
1861 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001862#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001863 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001864 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00001865 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001866 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001867 start_col++;
1868 }
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001869 /* If buf contains a control character, interpret it. If buf
David Lawrence Ramsey61f56732005-07-21 22:12:03 +00001870 * contains an invalid multibyte control character, display it
1871 * as such.*/
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001872 } else if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001873 char *ctrl_buf_mb = charalloc(mb_cur_max());
1874 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001875
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001876 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001877 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001878
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001879 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
1880 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001881
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001882 for (i = 0; i < ctrl_buf_mb_len; i++)
1883 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001884
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001885 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001886
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001887 free(ctrl_buf_mb);
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00001888 /* If buf contains a space character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001889 } else if (*buf_mb == ' ') {
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001890#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001891 if (ISSET(WHITESPACE_DISPLAY)) {
1892 int i;
1893
1894 for (i = whitespace_len[0]; i < whitespace_len[0] +
1895 whitespace_len[1]; i++)
1896 converted[index++] = whitespace[i];
1897 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001898#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001899 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001900 start_col++;
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001901 /* If buf contains a non-control character, interpret it. If
1902 * buf contains an invalid multibyte non-control character,
1903 * display it as such. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001904 } else {
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001905 char *nctrl_buf_mb = charalloc(mb_cur_max());
1906 int nctrl_buf_mb_len, i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001907
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001908 nctrl_buf_mb = mbrep(buf_mb, nctrl_buf_mb,
1909 &nctrl_buf_mb_len);
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001910
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001911 for (i = 0; i < nctrl_buf_mb_len; i++)
1912 converted[index++] = nctrl_buf_mb[i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001913
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001914 start_col += mbwidth(nctrl_buf_mb);
1915
1916 free(nctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001917 }
1918
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001919 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001920 }
1921
David Lawrence Ramsey6a0d5b82005-06-13 14:00:22 +00001922 free(buf_mb);
1923
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00001924 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00001925 converted[index] = '\0';
1926
1927 /* Make sure converted takes up no more than len columns. */
1928 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001929 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00001930
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001931 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001932}
1933
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001934/* Display the path specified in path on the titlebar, along with the
1935 * current version of nano and whether the current file has been
1936 * modified. If path is NULL, assume we're in normal editing mode and
1937 * display the current filename instead. Otherwise, assume we're in the
1938 * file browser, and don't display whether the current file has been
1939 * modified. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00001940void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001941{
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001942 int space = COLS;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001943 /* The space we have available for display. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001944 size_t verlen = strlenpt(VERMSG) + 1;
1945 /* The length of the version message in columns, plus one for
1946 * padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001947 const char *prefix;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001948 /* "DIR:", "File:", or "New Buffer". Goes before filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001949 size_t prefixlen;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001950 /* The length of the prefix in columns, plus one for padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001951 const char *state;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001952 /* "Modified", "View", or "". Shows the state of this
1953 * buffer. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001954 size_t statelen = 0;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001955 /* The length of the state in columns, or the length of
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00001956 * "Modified" if the state is blank. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001957 char *exppath = NULL;
1958 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001959 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001960 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001961 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001962 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001963
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00001964 assert(path != NULL || openfile->filename != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001965
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001966 wattron(topwin, A_REVERSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001967 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001968
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001969 /* space has to be at least 4: two spaces before the version message,
1970 * at least one character of the version message, and one space
1971 * after the version message. */
1972 if (space < 4)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001973 space = 0;
1974 else {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001975 /* Limit verlen to 1/3 the length of the screen in columns,
1976 * minus three columns for spaces. */
1977 if (verlen > (COLS / 3) - 3)
1978 verlen = (COLS / 3) - 3;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001979 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001980
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001981 if (space >= 4) {
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00001982 /* Add a space after the version message, and account for both
1983 * it and the two spaces before it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001984 mvwaddnstr(topwin, 0, 2, VERMSG, actual_x(VERMSG, verlen));
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001985 verlen += 3;
1986
1987 /* Account for the full length of the version message. */
1988 space -= verlen;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001989 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001990
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001991#ifndef DISABLE_BROWSER
1992 /* Don't display the state if we're in the file browser. */
1993 if (path != NULL)
1994 state = "";
1995 else
1996#endif
1997 state = openfile->modified ? _("Modified") : ISSET(VIEW_MODE) ?
1998 _("View") : "";
1999
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002000 statelen = strlenpt((state[0] != '\0') ? state : _("Modified"));
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002001
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002002 /* If possible, add a space before state. */
2003 if (space > 0 && statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002004 statelen++;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002005 else
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002006 goto the_end;
2007
2008#ifndef DISABLE_BROWSER
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002009 /* path should be a directory if we're in the file browser. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002010 if (path != NULL)
2011 prefix = _("DIR:");
2012 else
2013#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002014 if (openfile->filename[0] == '\0') {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002015 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002016 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002017 } else
2018 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002019
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002020 prefixlen = strnlenpt(prefix, space - statelen) + 1;
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002021
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002022 /* If newfie is FALSE, add a space after prefix. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002023 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002024 prefixlen++;
2025
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002026 /* If we're not in the file browser, path should be the current
2027 * filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002028 if (path == NULL)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002029 path = openfile->filename;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002030
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002031 /* Account for the full lengths of the prefix and the state. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002032 if (space >= prefixlen + statelen)
2033 space -= prefixlen + statelen;
2034 else
2035 space = 0;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002036 /* space is now the room we have for the filename. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002037
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002038 if (!newfie) {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002039 size_t lenpt = strlenpt(path), start_col;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002040
David Lawrence Ramseya03d9c02005-09-16 17:24:22 +00002041 dots = (lenpt >= space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002042
2043 if (dots) {
2044 start_col = lenpt - space + 3;
2045 space -= 3;
2046 } else
2047 start_col = 0;
2048
2049 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002050 }
2051
2052 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002053 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2054 /* The length of the expanded filename. */
2055
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002056 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002057 mvwaddnstr(topwin, 0, verlen + ((space - exppathlen) / 3),
2058 prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002059 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002060 waddch(topwin, ' ');
2061 waddstr(topwin, exppath);
2062 }
2063 } else {
2064 /* We will say something like "File: ...ename". */
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002065 mvwaddnstr(topwin, 0, verlen - 1, prefix, actual_x(prefix,
2066 prefixlen));
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002067 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002068 goto the_end;
2069 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002070 waddnstr(topwin, "...", space + 3);
2071 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002072 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002073 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002074 }
2075
2076 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002077 free(exppath);
2078
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002079 if (state[0] != '\0') {
David Lawrence Ramsey3d12f0f2005-10-26 23:14:59 +00002080 if (statelen >= COLS - 1)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002081 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
2082 else {
David Lawrence Ramseycaa86592005-07-10 23:57:32 +00002083 assert(COLS - statelen - 1 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002084
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002085 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002086 actual_x(state, statelen));
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002087 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002088 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002089
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002090 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002091
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002092 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002093 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002094 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002095}
2096
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002097/* Mark the current file as modified if it isn't already, and then
2098 * update the titlebar to display the file's new status. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002099void set_modified(void)
2100{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002101 if (!openfile->modified) {
2102 openfile->modified = TRUE;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002103 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002104 }
2105}
2106
David Lawrence Ramsey5593e202005-06-28 19:49:15 +00002107/* Display a message on the statusbar, and set disable_cursorpos to
2108 * TRUE, so that the message won't be immediately overwritten if
2109 * constant cursor position display is on. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002110void statusbar(const char *msg, ...)
2111{
2112 va_list ap;
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002113 char *bar, *foo;
2114 size_t start_x, foo_len;
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002115#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002116 bool old_whitespace;
2117#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002118
2119 va_start(ap, msg);
2120
2121 /* Curses mode is turned off. If we use wmove() now, it will muck
2122 * up the terminal settings. So we just use vfprintf(). */
2123 if (curses_ended) {
2124 vfprintf(stderr, msg, ap);
2125 va_end(ap);
2126 return;
2127 }
2128
2129 /* Blank out the line. */
2130 blank_statusbar();
2131
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002132#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002133 old_whitespace = ISSET(WHITESPACE_DISPLAY);
2134 UNSET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002135#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002136 bar = charalloc(mb_cur_max() * (COLS - 3));
2137 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
2138 va_end(ap);
2139 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002140#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002141 if (old_whitespace)
2142 SET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002143#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002144 free(bar);
2145 foo_len = strlenpt(foo);
2146 start_x = (COLS - foo_len - 4) / 2;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002147
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002148 wmove(bottomwin, 0, start_x);
2149 wattron(bottomwin, A_REVERSE);
2150 waddstr(bottomwin, "[ ");
2151 waddstr(bottomwin, foo);
2152 free(foo);
2153 waddstr(bottomwin, " ]");
2154 wattroff(bottomwin, A_REVERSE);
2155 wnoutrefresh(bottomwin);
2156 reset_cursor();
2157 wnoutrefresh(edit);
2158 /* Leave the cursor at its position in the edit window, not in
2159 * the statusbar. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002160
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002161 disable_cursorpos = TRUE;
David Lawrence Ramseyc6618532005-06-17 22:33:15 +00002162
2163 /* If we're doing quick statusbar blanking, and constant cursor
2164 * position display is off, blank the statusbar after only one
2165 * keystroke. Otherwise, blank it after twenty-five keystrokes,
2166 * as Pico does. */
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002167 statusblank =
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002168#ifndef NANO_TINY
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002169 ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 :
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002170#endif
2171 25;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002172}
2173
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002174/* Display the shortcut list in s on the last two rows of the bottom
2175 * portion of the window. */
Chris Allegretta6232d662002-05-12 19:52:15 +00002176void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002177{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002178 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002179
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002180 if (ISSET(NO_HELP))
2181 return;
2182
Chris Allegretta6232d662002-05-12 19:52:15 +00002183 if (s == main_list) {
2184 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002185
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002186 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002187 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002188 slen = length_of_list(s);
2189
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002190 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002191 if (slen > MAIN_VISIBLE)
2192 slen = MAIN_VISIBLE;
2193 }
2194
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002195 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002196 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002197 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002198
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002199 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002200
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002201 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002202 const char *keystr;
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002203 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002204
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002205 /* Yucky sentinel values that we can't handle a better way. */
2206 if (s->ctrlval == NANO_CONTROL_SPACE)
2207 strcpy(foo, "^ ");
2208 else if (s->ctrlval == NANO_CONTROL_8)
2209 strcpy(foo, "^?");
2210 /* Normal values. Assume that the shortcut has an equivalent
2211 * control key, meta key sequence, or both. */
2212 else if (s->ctrlval != NANO_NO_KEY)
2213 sprintf(foo, "^%c", s->ctrlval + 64);
2214 else if (s->metaval != NANO_NO_KEY)
2215 sprintf(foo, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00002216
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002217 keystr = foo;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002218
2219 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002220 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002221 }
2222
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002223 wnoutrefresh(bottomwin);
2224 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002225 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002226}
2227
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002228/* Write a shortcut key to the help area at the bottom of the window.
2229 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2230 * to write at most len characters, even if len is very small and
2231 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2232 * the whole string! We do not bother padding the entry with blanks. */
2233void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002234{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002235 size_t keystroke_len = strlenpt(keystroke) + 1;
2236
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002237 assert(keystroke != NULL && desc != NULL);
2238
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002239 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002240 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002241 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002242
2243 if (len > keystroke_len)
2244 len -= keystroke_len;
2245 else
2246 len = 0;
2247
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002248 if (len > 0) {
2249 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002250 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002251 }
2252}
2253
David Lawrence Ramsey2b9d6a02005-11-01 17:45:31 +00002254/* Reset current_y, based on the position of current, and put the cursor
2255 * in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002256void reset_cursor(void)
2257{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002258 /* If we haven't opened any files yet, put the cursor in the top
2259 * left corner of the edit window and get out. */
David Lawrence Ramseydbcaa3b2005-07-08 20:59:24 +00002260 if (openfile == NULL) {
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002261 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002262 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002263 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002264
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002265 openfile->current_y = openfile->current->lineno -
2266 openfile->edittop->lineno;
2267 if (openfile->current_y < editwinrows) {
David Lawrence Ramseycfffbf72005-11-16 03:14:11 +00002268 size_t xpt = xplustabs();
2269 wmove(edit, openfile->current_y, xpt - get_page_start(xpt));
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002270 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002271}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002272
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002273/* edit_draw() takes care of the job of actually painting a line into
2274 * the edit window. fileptr is the line to be painted, at row line of
2275 * the window. converted is the actual string to be written to the
2276 * window, with tabs and control characters replaced by strings of
2277 * regular characters. start is the column number of the first
2278 * character of this page. That is, the first character of converted
2279 * corresponds to character number actual_x(fileptr->data, start) of the
2280 * line. */
2281void edit_draw(const filestruct *fileptr, const char *converted, int
2282 line, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002283{
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002284#if !defined(NANO_TINY) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002285 size_t startpos = actual_x(fileptr->data, start);
2286 /* The position in fileptr->data of the leftmost character
2287 * that displays at least partially on the window. */
2288 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2289 /* The position in fileptr->data of the first character that is
2290 * completely off the window to the right.
2291 *
2292 * Note that endpos might be beyond the null terminator of the
2293 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002294#endif
2295
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002296 assert(openfile != NULL && fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002297 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002298
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002299 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002300 * just the text that needs it). */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002301 mvwaddstr(edit, line, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002302
Chris Allegretta7dd77682001-12-08 19:52:28 +00002303#ifdef ENABLE_COLOR
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002304 /* If color syntaxes are available and turned on, we need to display
2305 * them. */
2306 if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
2307 const colortype *tmpcolor = openfile->colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002308
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002309 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2310 int x_start;
2311 /* Starting column for mvwaddnstr. Zero-based. */
2312 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002313 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002314 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002315 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002316 /* Index in converted where we paint. */
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002317 regmatch_t startmatch;
2318 /* Match position for start_regex. */
2319 regmatch_t endmatch;
2320 /* Match position for end_regex. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002321
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002322 if (tmpcolor->bright)
2323 wattron(edit, A_BOLD);
2324 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramseyb0e04c02005-12-08 07:24:54 +00002325 /* Two notes about regexec(). A return value of zero means
2326 * that there is a match. Also, rm_eo is the first
2327 * non-matching character after the match. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002328
2329 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002330 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002331 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002332
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002333 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002334 * last match. Even though two matches may overlap, we
2335 * want to ignore them, so that we can highlight
2336 * C-strings correctly. */
2337 while (k < endpos) {
2338 /* Note the fifth parameter to regexec(). It says
2339 * not to match the beginning-of-line character
2340 * unless k is 0. If regexec() returns REG_NOMATCH,
2341 * there are no more matches in the line. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002342 if (regexec(tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002343 &startmatch, (k == 0) ? 0 : REG_NOTBOL) ==
2344 REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002345 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002346 /* Translate the match to the beginning of the
2347 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002348 startmatch.rm_so += k;
2349 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002350 if (startmatch.rm_so == startmatch.rm_eo) {
2351 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002352 statusbar(
2353 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002354 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002355 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002356 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002357 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002358 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002359 x_start = strnlenpt(fileptr->data,
2360 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002361
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002362 index = actual_x(converted, x_start);
2363
2364 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00002365 strnlenpt(fileptr->data,
2366 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002367
2368 assert(0 <= x_start && 0 <= paintlen);
2369
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002370 mvwaddnstr(edit, line, x_start, converted +
2371 index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002372 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002373 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002374 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002375 } else {
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002376 /* This is a multi-line regex. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002377 * First, we have to see if the beginning of the line is
2378 * colored by a start on an earlier line, and an end on
2379 * this line or later.
2380 *
2381 * We find the first line before fileptr matching the
2382 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002383 * end, then go to step two. Otherwise, find the next
2384 * line after start_line matching the end. If that line
2385 * is not before fileptr, then paint the beginning of
2386 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002387 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002388 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002389 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002390 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002391 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002392
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002393 while (start_line != NULL && regexec(tmpcolor->start,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002394 start_line->data, 1, &startmatch, 0) ==
2395 REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002396 /* If there is an end on this line, there is no need
2397 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002398 if (regexec(tmpcolor->end, start_line->data, 0,
2399 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002400 goto step_two;
2401 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002402 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002403 /* No start found, so skip to the next step. */
2404 if (start_line == NULL)
2405 goto step_two;
2406 /* Now start_line is the first line before fileptr
2407 * containing a start match. Is there a start on this
2408 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002409 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002410 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002411 start_col += startmatch.rm_so;
2412 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002413 if (regexec(tmpcolor->end, start_line->data +
2414 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002415 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002416 REG_NOTBOL) == REG_NOMATCH)
2417 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002418 break;
2419 start_col++;
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002420 if (regexec(tmpcolor->start, start_line->data +
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002421 start_col, 1, &startmatch,
2422 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002423 /* No later start on this line. */
2424 goto step_two;
2425 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002426 /* Indeed, there is a start not followed on this line by
2427 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002428
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002429 /* We have already checked that there is no end before
2430 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002431 * the start at all? We don't paint unterminated
2432 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002433 end_line = fileptr;
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002434 while (end_line != NULL && regexec(tmpcolor->end,
2435 end_line->data, 1, &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002436 end_line = end_line->next;
2437
2438 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002439 if (end_line == NULL || (end_line == fileptr &&
2440 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002441 goto step_two;
2442
2443 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00002444 if (end_line != fileptr)
2445 /* If the start of fileptr is on a different line
2446 * from the end, paintlen is -1, meaning that
2447 * everything on the line gets painted. */
2448 paintlen = -1;
2449 else
2450 /* Otherwise, paintlen is the expanded location of
2451 * the end of the match minus the expanded location
2452 * of the beginning of the page. */
2453 paintlen = actual_x(converted,
2454 strnlenpt(fileptr->data, endmatch.rm_eo) -
2455 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002456
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002457 mvwaddnstr(edit, line, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002458
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002459 step_two:
2460 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002461 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002462
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002463 while (start_col < endpos) {
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002464 if (regexec(tmpcolor->start, fileptr->data +
2465 start_col, 1, &startmatch, (start_col == 0) ?
2466 0 : REG_NOTBOL) == REG_NOMATCH || start_col +
2467 startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002468 /* No more starts on this line. */
2469 break;
2470 /* Translate the match to be relative to the
2471 * beginning of the line. */
2472 startmatch.rm_so += start_col;
2473 startmatch.rm_eo += start_col;
2474
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002475 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002476 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002477 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002478 x_start = strnlenpt(fileptr->data,
2479 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002480
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002481 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002482
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002483 if (regexec(tmpcolor->end, fileptr->data +
2484 startmatch.rm_eo, 1, &endmatch,
2485 (startmatch.rm_eo == 0) ? 0 : REG_NOTBOL) ==
2486 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002487 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002488 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002489 endmatch.rm_so += startmatch.rm_eo;
2490 endmatch.rm_eo += startmatch.rm_eo;
2491 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002492 * appear on this page, and is the match more
2493 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002494 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002495 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002496 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00002497 strnlenpt(fileptr->data,
2498 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002499
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002500 assert(0 <= x_start && x_start < COLS);
2501
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002502 mvwaddnstr(edit, line, x_start, converted +
2503 index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002504 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002505 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002506 /* There is no end on this line. But we haven't
2507 * yet looked for one on later lines. */
2508 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002509
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002510 while (end_line != NULL &&
2511 regexec(tmpcolor->end, end_line->data,
2512 0, NULL, 0) == REG_NOMATCH)
2513 end_line = end_line->next;
2514
2515 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002516 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002517
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002518 mvwaddnstr(edit, line, x_start, converted +
2519 index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002520 /* We painted to the end of the line, so
2521 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002522 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002523 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002524 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002525 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002526 }
2527 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002528
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002529 wattroff(edit, A_BOLD);
2530 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002531 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002532 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002533#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002534
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002535#ifndef NANO_TINY
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002536 /* If the mark is on, we need to display it. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002537 if (openfile->mark_set && (fileptr->lineno <=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002538 openfile->mark_begin->lineno || fileptr->lineno <=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002539 openfile->current->lineno) && (fileptr->lineno >=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002540 openfile->mark_begin->lineno || fileptr->lineno >=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002541 openfile->current->lineno)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002542 /* fileptr is at least partially selected. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002543 const filestruct *top;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002544 /* Either current or mark_begin, whichever is first. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002545 size_t top_x;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002546 /* current_x or mark_begin_x, corresponding to top. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002547 const filestruct *bot;
2548 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002549 int x_start;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002550 /* Starting column for mvwaddnstr(). Zero-based. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002551 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002552 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002553 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002554 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002555 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002556
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00002557 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002558
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002559 if (top->lineno < fileptr->lineno || top_x < startpos)
2560 top_x = startpos;
2561 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2562 bot_x = endpos;
2563
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002564 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002565 if (top_x < endpos && bot_x > startpos) {
2566 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002567
2568 /* x_start is the expanded location of the beginning of the
2569 * mark minus the beginning of the page. */
2570 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002571
2572 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002573 /* If the end of the mark is off the page, paintlen is
2574 * -1, meaning that everything on the line gets
2575 * painted. */
2576 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002577 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002578 /* Otherwise, paintlen is the expanded location of the
2579 * end of the mark minus the expanded location of the
2580 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002581 paintlen = strnlenpt(fileptr->data, bot_x) -
2582 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002583
2584 /* If x_start is before the beginning of the page, shift
2585 * paintlen x_start characters to compensate, and put
2586 * x_start at the beginning of the page. */
2587 if (x_start < 0) {
2588 paintlen += x_start;
2589 x_start = 0;
2590 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002591
2592 assert(x_start >= 0 && x_start <= strlen(converted));
2593
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002594 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002595
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002596 if (paintlen > 0)
2597 paintlen = actual_x(converted + index, paintlen);
2598
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002599 wattron(edit, A_REVERSE);
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002600 mvwaddnstr(edit, line, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00002601 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002602 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002603 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002604 }
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002605#endif /* !NANO_TINY */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002606}
2607
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002608/* Just update one line in the edit buffer. This is basically a wrapper
David Lawrence Ramseyb3c6b402005-11-07 06:20:02 +00002609 * for edit_draw(). The line will be displayed starting with
2610 * fileptr->data[index]. Likely arguments are current_x or zero. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002611void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002612{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002613 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002614 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002615 char *converted;
2616 /* fileptr->data converted to have tabs and control characters
2617 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002618 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002619
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002620 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002621
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002622 line = fileptr->lineno - openfile->edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002623
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002624 /* We assume the line numbers are valid. Is that really true? */
2625 assert(line < 0 || line == check_linenumbers(fileptr));
2626
2627 if (line < 0 || line >= editwinrows)
2628 return;
2629
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002630 /* First, blank out the line. */
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002631 blank_line(edit, line, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002632
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002633 /* Next, convert variables that index the line to their equivalent
2634 * positions in the expanded line. */
David Lawrence Ramseyb3c6b402005-11-07 06:20:02 +00002635 index = strnlenpt(fileptr->data, index);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002636 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002637
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002638 /* Expand the line, replacing tabs with spaces, and control
2639 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002640 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00002641
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002642 /* Paint the line. */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002643 edit_draw(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002644 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002645
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002646 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002647 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002648 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002649 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002650}
2651
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002652/* Return TRUE if we need an update after moving horizontally, and FALSE
2653 * otherwise. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002654 * placewewant are on different pages. */
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002655bool need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002656{
2657 return
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002658#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002659 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002660#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002661 get_page_start(old_pww) !=
2662 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002663}
2664
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002665/* Return TRUE if we need an update after moving vertically, and FALSE
2666 * otherwise. We need one if the mark is on or if old_pww and
2667 * placewewant are on different pages. */
2668bool need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002669{
2670 return
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002671#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002672 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002673#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002674 get_page_start(old_pww) !=
2675 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002676}
2677
2678/* Scroll the edit window in the given direction and the given number
2679 * of lines, and draw new lines on the blank lines left after the
2680 * scrolling. direction is the direction to scroll, either UP or DOWN,
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002681 * and nlines is the number of lines to scroll. We change edittop, and
David Lawrence Ramsey6969c992005-07-26 00:42:48 +00002682 * assume that current and current_x are up to date. We also assume
2683 * that scrollok(edit) is FALSE. */
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002684void edit_scroll(scroll_dir direction, ssize_t nlines)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002685{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002686 bool do_redraw = need_vertical_update(0);
David Lawrence Ramsey443a7662005-07-14 23:06:22 +00002687 const filestruct *foo;
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002688 ssize_t i;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002689
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002690 /* Don't bother scrolling less than one line. */
2691 if (nlines < 1)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002692 return;
2693
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002694 /* Part 1: nlines is the number of lines we're going to scroll the
2695 * text of the edit window. */
2696
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002697 /* Move the top line of the edit window up or down (depending on the
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002698 * value of direction) nlines lines, or as many lines as we can if
2699 * there are fewer than nlines lines available. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002700 for (i = nlines; i > 0; i--) {
2701 if (direction == UP) {
David Lawrence Ramseye99223d2005-11-10 04:27:30 +00002702 if (openfile->edittop == openfile->fileage)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002703 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002704 openfile->edittop = openfile->edittop->prev;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002705 } else {
David Lawrence Ramseye99223d2005-11-10 04:27:30 +00002706 if (openfile->edittop == openfile->filebot)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002707 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002708 openfile->edittop = openfile->edittop->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002709 }
2710 }
2711
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00002712 /* Limit nlines to the number of lines we could scroll. */
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00002713 nlines -= i;
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00002714
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00002715 /* Don't bother scrolling zero lines or more than the number of
2716 * lines in the edit window minus one; in both cases, get out, and
2717 * in the latter case, call edit_refresh() beforehand. */
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00002718 if (nlines == 0)
2719 return;
2720
2721 if (nlines >= editwinrows) {
2722 edit_refresh();
2723 return;
2724 }
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002725
2726 /* Scroll the text of the edit window up or down nlines lines,
2727 * depending on the value of direction. */
David Lawrence Ramsey47bb8882005-07-22 22:56:03 +00002728 scrollok(edit, TRUE);
2729 wscrl(edit, (direction == UP) ? -nlines : nlines);
2730 scrollok(edit, FALSE);
2731
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002732 /* Part 2: nlines is the number of lines in the scrolled region of
2733 * the edit window that we need to draw. */
2734
David Lawrence Ramsey68346502005-08-16 03:03:15 +00002735 /* If the top or bottom line of the file is now visible in the edit
2736 * window, we need to draw the entire edit window. */
2737 if ((direction == UP && openfile->edittop == openfile->fileage) ||
2738 (direction == DOWN && openfile->edittop->lineno + editwinrows -
2739 1 >= openfile->filebot->lineno))
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00002740 nlines = editwinrows;
David Lawrence Ramseya7f488b2005-07-17 02:19:47 +00002741
David Lawrence Ramseya6eb8482006-01-10 07:51:49 +00002742 /* If the scrolled region contains only one line, and the line
2743 * before it is visible in the edit window, we need to draw it too.
2744 * If the scrolled region contains more than one line, and the lines
2745 * before and after the scrolled region are visible in the edit
2746 * window, we need to draw them too. */
2747 nlines += (nlines == 1) ? 1 : 2;
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00002748
David Lawrence Ramseyde0c5eb2005-07-17 22:51:44 +00002749 if (nlines > editwinrows)
2750 nlines = editwinrows;
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002751
2752 /* If we scrolled up, we're on the line before the scrolled
2753 * region. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002754 foo = openfile->edittop;
David Lawrence Ramsey14588912005-07-14 20:37:01 +00002755
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002756 /* If we scrolled down, move down to the line before the scrolled
2757 * region. */
David Lawrence Ramsey14588912005-07-14 20:37:01 +00002758 if (direction == DOWN) {
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002759 for (i = editwinrows - nlines; i > 0 && foo != NULL; i--)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002760 foo = foo->next;
2761 }
2762
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002763 /* Draw new lines on any blank lines before or inside the scrolled
2764 * region. If we scrolled down and we're on the top line, or if we
2765 * scrolled up and we're on the bottom line, the line won't be
2766 * blank, so we don't need to draw it unless the mark is on or we're
2767 * not on the first page. */
2768 for (i = nlines; i > 0 && foo != NULL; i--) {
2769 if ((i == nlines && direction == DOWN) || (i == 1 &&
2770 direction == UP)) {
2771 if (do_redraw)
2772 update_line(foo, (foo == openfile->current) ?
2773 openfile->current_x : 0);
2774 } else
2775 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002776 openfile->current_x : 0);
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00002777 foo = foo->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002778 }
2779}
2780
2781/* Update any lines between old_current and current that need to be
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00002782 * updated. Use this if we've moved without changing any text. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002783void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002784{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002785 bool do_redraw = need_vertical_update(0) ||
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00002786 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002787 const filestruct *foo;
2788
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002789 /* If either old_current or current is offscreen, scroll the edit
2790 * window until it's onscreen and get out. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002791 if (old_current->lineno < openfile->edittop->lineno ||
2792 old_current->lineno >= openfile->edittop->lineno +
2793 editwinrows || openfile->current->lineno <
2794 openfile->edittop->lineno || openfile->current->lineno >=
2795 openfile->edittop->lineno + editwinrows) {
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002796 filestruct *old_edittop = openfile->edittop;
2797 ssize_t nlines;
2798
2799 /* Put edittop in range of current, get the difference in lines
2800 * between the original edittop and the current edittop, and
2801 * then restore the original edittop. */
2802 edit_update(
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002803#ifndef NANO_TINY
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002804 ISSET(SMOOTH_SCROLL) ? NONE :
2805#endif
2806 CENTER);
2807
2808 nlines = openfile->edittop->lineno - old_edittop->lineno;
2809
2810 openfile->edittop = old_edittop;
2811
David Lawrence Ramseya6eb8482006-01-10 07:51:49 +00002812 /* Update old_current if we're not on the first page and/or
2813 * we're not on the same page as before. */
2814 if (do_redraw)
2815 update_line(old_current, 0);
2816
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00002817 /* Scroll the edit window up or down until edittop is in range
2818 * of current. */
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002819 if (nlines < 0)
2820 edit_scroll(UP, -nlines);
2821 else
2822 edit_scroll(DOWN, nlines);
2823
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002824 return;
2825 }
2826
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00002827 /* Update old_current and current if we're not on the first page
2828 * and/or we're not on the same page as before. If the mark is on,
2829 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002830 foo = old_current;
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00002831
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002832 while (foo != openfile->current) {
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002833 if (do_redraw)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002834 update_line(foo, 0);
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00002835
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002836#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002837 if (!openfile->mark_set)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002838#endif
2839 break;
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00002840
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002841#ifndef NANO_TINY
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00002842 foo = (foo->lineno > openfile->current->lineno) ? foo->prev :
2843 foo->next;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002844#endif
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002845 }
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00002846
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002847 if (do_redraw)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002848 update_line(openfile->current, openfile->current_x);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002849}
2850
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00002851/* Refresh the screen without changing the position of lines. Use this
2852 * if we've moved and changed text. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002853void edit_refresh(void)
2854{
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002855 const filestruct *foo;
2856 int nlines;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002857
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002858 if (openfile->current->lineno < openfile->edittop->lineno ||
2859 openfile->current->lineno >= openfile->edittop->lineno +
2860 editwinrows)
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002861 /* Put the top line of the edit window in range of the current
2862 * line. */
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002863 edit_update(
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002864#ifndef NANO_TINY
David Lawrence Ramseyb2b69762005-06-16 02:13:10 +00002865 ISSET(SMOOTH_SCROLL) ? NONE :
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002866#endif
2867 CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002868
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002869 foo = openfile->edittop;
2870
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002871#ifdef DEBUG
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002872 fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", (long)openfile->edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002873#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002874
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002875 for (nlines = 0; nlines < editwinrows && foo != NULL; nlines++) {
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002876 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002877 openfile->current_x : 0);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002878 foo = foo->next;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002879 }
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002880
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002881 for (; nlines < editwinrows; nlines++)
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002882 blank_line(edit, nlines, 0, COLS);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002883
2884 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002885 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002886}
2887
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002888/* Move edittop to put it in range of current, keeping current in the
2889 * same place. location determines how we move it: if it's CENTER, we
2890 * center current, and if it's NONE, we put current current_y lines
2891 * below edittop. */
David Lawrence Ramseybf0e47d2005-08-01 18:27:10 +00002892void edit_update(update_type location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002893{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002894 filestruct *foo = openfile->current;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002895 int goal;
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00002896
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002897 /* If location is CENTER, we move edittop up (editwinrows / 2)
2898 * lines. This puts current at the center of the screen. If
2899 * location is NONE, we move edittop up current_y lines if current_y
2900 * is in range of the screen, 0 lines if current_y is less than 0,
2901 * or (editwinrows - 1) lines if current_y is greater than
2902 * (editwinrows - 1). This puts current at the same place on the
2903 * screen as before, or at the top or bottom of the screen if
2904 * edittop is beyond either. */
2905 if (location == CENTER)
2906 goal = editwinrows / 2;
2907 else {
2908 goal = openfile->current_y;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002909
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002910 /* Limit goal to (editwinrows - 1) lines maximum. */
2911 if (goal > editwinrows - 1)
2912 goal = editwinrows - 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002913 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002914
David Lawrence Ramseyb885c9c2005-11-10 05:20:25 +00002915 for (; goal > 0 && foo->prev != NULL; goal--)
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002916 foo = foo->prev;
2917
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002918 openfile->edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002919}
2920
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002921/* Unconditionally redraw the entire screen. */
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00002922void total_redraw(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002923{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002924#ifdef USE_SLANG
2925 /* Slang curses emulation brain damage, part 3: Slang doesn't define
2926 * curscr. */
2927 SLsmg_touch_screen();
2928 SLsmg_refresh();
2929#else
2930 wrefresh(curscr);
2931#endif
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002932}
2933
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002934/* Unconditionally redraw the entire screen, and then refresh it using
2935 * the current file. */
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002936void total_refresh(void)
2937{
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00002938 total_redraw();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002939 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00002940 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002941 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002942}
2943
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002944/* Display the main shortcut list on the last two rows of the bottom
2945 * portion of the window. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002946void display_main_list(void)
2947{
2948 bottombars(main_list);
2949}
2950
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00002951/* If constant is TRUE, we display the current cursor position only if
2952 * disable_cursorpos is FALSE. Otherwise, we display it
2953 * unconditionally and set disable_cursorpos to FALSE. If constant is
2954 * TRUE and disable_cursorpos is TRUE, we also set disable_cursorpos to
2955 * FALSE, so that we leave the current statusbar alone this time, and
2956 * display the current cursor position next time. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00002957void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002958{
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00002959 filestruct *f;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00002960 char c;
David Lawrence Ramsey5745c0a2005-07-31 20:20:37 +00002961 size_t i, cur_xpt = xplustabs() + 1;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002962 size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00002963 int linepct, colpct, charpct;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002964
David Lawrence Ramsey4ab80152005-07-31 18:51:51 +00002965 assert(openfile->fileage != NULL && openfile->current != NULL);
Chris Allegretta2084acc2001-11-29 03:43:08 +00002966
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00002967 f = openfile->current->next;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00002968 c = openfile->current->data[openfile->current_x];
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00002969
2970 openfile->current->next = NULL;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00002971 openfile->current->data[openfile->current_x] = '\0';
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00002972
2973 i = get_totsize(openfile->fileage, openfile->current);
2974
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00002975 openfile->current->data[openfile->current_x] = c;
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00002976 openfile->current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00002977
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002978 if (constant && disable_cursorpos) {
2979 disable_cursorpos = FALSE;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00002980 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00002981 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00002982
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00002983 /* Display the current cursor position on the statusbar, and set
2984 * disable_cursorpos to FALSE. */
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00002985 linepct = 100 * openfile->current->lineno /
2986 openfile->filebot->lineno;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00002987 colpct = 100 * cur_xpt / cur_lenpt;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002988 charpct = (openfile->totsize == 0) ? 0 : 100 * i /
2989 openfile->totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00002990
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00002991 statusbar(
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00002992 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002993 (long)openfile->current->lineno,
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00002994 (long)openfile->filebot->lineno, linepct,
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00002995 (unsigned long)cur_xpt, (unsigned long)cur_lenpt, colpct,
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002996 (unsigned long)i, (unsigned long)openfile->totsize, charpct);
Chris Allegretta2084acc2001-11-29 03:43:08 +00002997
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00002998 disable_cursorpos = FALSE;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002999}
3000
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003001/* Unconditionally display the current cursor position. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003002void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003003{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003004 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003005}
3006
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003007/* Highlight the current word being replaced or spell checked. We
3008 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003009void do_replace_highlight(bool highlight, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003010{
David Lawrence Ramsey6168cb72005-06-30 03:53:28 +00003011 size_t y = xplustabs(), word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003012
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003013 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003014 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003015 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003016
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003017 assert(y > 0);
3018
3019 if (word_len > y)
3020 y--;
3021
Chris Allegrettafb62f732000-12-05 11:36:41 +00003022 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003023
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003024 if (highlight)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003025 wattron(edit, A_REVERSE);
3026
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003027#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003028 /* This is so we can show zero-length regexes. */
3029 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00003030 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003031 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003032#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003033 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003034
3035 if (word_len > y)
3036 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003037
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003038 if (highlight)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003039 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003040}
3041
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003042#ifdef NANO_EXTRA
David Lawrence Ramsey315eb322005-11-28 19:35:29 +00003043#define CREDIT_LEN 55
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003044#define XLCREDIT_LEN 8
3045
David Lawrence Ramsey8ad58bc2005-08-16 03:02:46 +00003046/* Easter egg: Display credits. Assume nodelay(edit) and scrollok(edit)
3047 * are FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003048void do_credits(void)
3049{
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003050 bool old_more_space = ISSET(MORE_SPACE);
3051 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003052 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003053 const char *credits[CREDIT_LEN] = {
3054 NULL, /* "The nano text editor" */
3055 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003056 VERSION,
3057 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003058 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003059 "Chris Allegretta",
3060 "Jordi Mallach",
3061 "Adam Rogoyski",
3062 "Rob Siemborski",
3063 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003064 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003065 "David Benbennick",
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003066 "Mike Frysinger",
Chris Allegretta598106e2002-01-19 01:59:37 +00003067 "Ken Tyler",
3068 "Sven Guckes",
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003069 NULL, /* credits[15], handled below. */
Chris Allegretta598106e2002-01-19 01:59:37 +00003070 "Pauli Virtanen",
3071 "Daniele Medri",
3072 "Clement Laforet",
3073 "Tedi Heriyanto",
3074 "Bill Soudan",
3075 "Christian Weisgerber",
3076 "Erik Andersen",
3077 "Big Gaute",
3078 "Joshua Jensen",
3079 "Ryan Krebs",
3080 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003081 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003082 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003083 "Plattsburgh State University",
3084 "Benet Laboratories",
3085 "Amy Allegretta",
3086 "Linda Young",
3087 "Jeremy Robichaud",
3088 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003089 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003090 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003091 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003092 "Thomas Dickey",
3093 "Pavel Curtis",
3094 "Zeyd Ben-Halim",
3095 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003096 NULL, /* "and anyone else we forgot..." */
3097 NULL, /* "Thank you for using nano!" */
3098 "",
3099 "",
3100 "",
3101 "",
David Lawrence Ramsey315eb322005-11-28 19:35:29 +00003102 "(c) 1999-2004 Chris Allegretta",
3103 "(c) 2005 David Lawrence Ramsey",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003104 "",
3105 "",
3106 "",
3107 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003108 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003109 };
3110
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003111 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003112 N_("The nano text editor"),
3113 N_("version"),
3114 N_("Brought to you by:"),
3115 N_("Special thanks to:"),
3116 N_("The Free Software Foundation"),
3117 N_("For ncurses:"),
3118 N_("and anyone else we forgot..."),
3119 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003120 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003121
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003122 /* credits[15]: Make sure this name is displayed properly, since we
David Lawrence Ramsey62d616b2005-07-06 19:20:32 +00003123 * can't dynamically assign it above, using Unicode 00F6 (Latin
3124 * Small Letter O with Diaresis) if applicable. */
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003125 credits[15] =
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00003126#ifdef ENABLE_UTF8
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003127 ISSET(USE_UTF8) ? "Florian K\xC3\xB6nig" :
3128#endif
3129 "Florian K\xF6nig";
3130
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003131 if (!old_more_space || !old_no_help) {
3132 SET(MORE_SPACE);
3133 SET(NO_HELP);
3134 window_init();
3135 }
3136
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003137 curs_set(0);
3138 nodelay(edit, TRUE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003139
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003140 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003141 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003142 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003143 blank_statusbar();
3144 blank_bottombars();
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003145
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003146 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003147 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003148 wrefresh(bottomwin);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003149 napms(700);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003150
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003151 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003152 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003153 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003154
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003155 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003156 const char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003157 size_t start_x;
3158
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003159 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003160 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003161
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003162 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003163 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003164 } else
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003165 what = credits[crpos];
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003166
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003167 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003168 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
3169 start_x, what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003170 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003171
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003172 wrefresh(edit);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003173
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003174 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003175 break;
3176 napms(700);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003177
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003178 scrollok(edit, TRUE);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003179 wscrl(edit, 1);
3180 scrollok(edit, FALSE);
3181 wrefresh(edit);
3182
3183 if ((kbinput = wgetch(edit)) != ERR)
3184 break;
3185 napms(700);
3186
3187 scrollok(edit, TRUE);
3188 wscrl(edit, 1);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003189 scrollok(edit, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003190 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003191 }
3192
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003193 if (kbinput != ERR)
3194 ungetch(kbinput);
3195
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003196 if (!old_more_space || !old_no_help) {
3197 UNSET(MORE_SPACE);
3198 UNSET(NO_HELP);
3199 window_init();
3200 }
3201
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003202 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003203 nodelay(edit, FALSE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003204
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003205 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003206}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003207#endif