blob: d922de2081917655b8e32125153a689392295c5d [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 Ramseyf21cd102002-06-13 00:40:19 +000030#include <ctype.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000031
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +000032static int *key_buffer = NULL;
David Lawrence Ramsey74835712004-12-04 17:41:52 +000033 /* The default keystroke buffer,
34 * containing all the keystrokes we have
35 * at a given point. */
36static size_t key_buffer_len = 0;
37 /* The length of the default keystroke
38 * buffer. */
David Lawrence Ramseyfe7d53e2005-06-25 20:56:36 +000039static int statusblank = 0;
40 /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000041 * we call statusbar(), before we
42 * actually blank the statusbar. */
David Lawrence Ramseyea014742005-06-17 18:27:00 +000043static bool disable_cursorpos = FALSE;
44 /* Should we temporarily disable
45 * constant cursor position display? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000046
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000047/* Control character compatibility:
48 *
49 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
50 * VT100, and VT220.
51 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
52 * VT220, and VT320.
53 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
54 * VT220, and VT320.
55 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
56 * VT220, and VT320.
57 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
58 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000059 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000060 * ANSI, VT100, and VT220, and which is Backspace under VT320.
61 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000062 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000063 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
64 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000065 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000066 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000067 * on which the VT320 sequences are translated by the keypad to KEY_DC
68 * and [nothing]. We work around this conflict via the REBIND_DELETE
69 * flag: if it's not set, we assume VT320 compatibility, and if it is,
70 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
71 * Hemel for helping work this conflict out.
72 *
73 * Escape sequence compatibility:
74 *
75 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000076 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000077 * console), xterm, rxvt, and Eterm. Among these, there are several
78 * conflicts and omissions, outlined as follows:
79 *
80 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
81 * (Ctrl-I is also Tab on ANSI, which we already support.)
82 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
83 * NumLock off on Linux console; the latter is omitted. (The editing
84 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000085 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000086 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
87 * latter is omitted. (Mouse input will only work properly if the
88 * extended keypad value KEY_MOUSE is generated on mouse events
89 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000090 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000091 * omitted. (The editing keypad is more important to have working
92 * than the function keys, because the functions of the former are not
93 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000094 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000095 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000096 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000097 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +000098 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
99 * omitted. (The arrow keys, with or without modifiers, are more
100 * important to have working than the function keys, because the
101 * functions of the former are not arbitrary and the functions of the
102 * latter are.)
103 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
104 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000105 *
106 * Note that Center (5) on the numeric keypad with NumLock off can also
107 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000108
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000109#ifndef NANO_TINY
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000110/* Reset all the input routines that rely on character sequences. */
111void reset_kbinput(void)
112{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000113 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000114 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey6a836472005-08-01 19:12:05 +0000115 get_unicode_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000116}
117#endif
118
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000119/* Read in a sequence of keystrokes from win and save them in the
120 * default keystroke buffer. This should only be called when the
121 * default keystroke buffer is empty. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000122void get_key_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000123{
David Lawrence Ramseyec8a0552006-03-19 19:26:52 +0000124 int input;
125 size_t errcount;
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 Ramsey91493252006-03-19 19:25:29 +0000140 errcount = 0;
David Lawrence Ramsey6f5de422005-10-06 05:28:37 +0000141 while ((input = wgetch(win)) == ERR) {
David Lawrence Ramsey91493252006-03-19 19:25:29 +0000142 errcount++;
143
David Lawrence Ramsey354597f2006-03-24 16:04:44 +0000144 /* If we've failed to get a character MAX_BUF_SIZE times in a
145 * row, assume that the input source we were using is gone and
David Lawrence Ramsey9b33d512006-03-20 04:46:48 +0000146 * die gracefully. We could check if errno is set to EIO
147 * ("Input/output error") and die gracefully in that case, but
148 * it's not always set properly. Argh. */
David Lawrence Ramsey354597f2006-03-24 16:04:44 +0000149 if (errcount == MAX_BUF_SIZE)
David Lawrence Ramsey6f5de422005-10-06 05:28:37 +0000150 handle_hupterm(0);
151 }
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000152
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000153#ifndef NANO_TINY
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000154 allow_pending_sigwinch(FALSE);
155#endif
156
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000157 /* Increment the length of the keystroke buffer, save the value of
158 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000159 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000160 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000161 key_buffer = (int *)nmalloc(sizeof(int));
162 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000163
164 /* Read in the remaining characters using non-blocking input. */
165 nodelay(win, TRUE);
166
167 while (TRUE) {
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000168#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000169 allow_pending_sigwinch(TRUE);
170#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000171
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000172 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000173
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000174 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000175 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000176 break;
177
178 /* Otherwise, increment the length of the keystroke buffer, save
179 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000180 * if the keystroke is an extended keypad value or FALSE if it
181 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000182 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000183 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
184 sizeof(int));
185 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000186
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000187#ifndef NANO_TINY
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000188 allow_pending_sigwinch(FALSE);
189#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000190 }
191
192 /* Switch back to non-blocking input. */
193 nodelay(win, FALSE);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000194
195#ifdef DEBUG
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000196 fprintf(stderr, "get_key_buffer(): key_buffer_len = %lu\n", (unsigned long)key_buffer_len);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000197#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000198}
199
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000200/* Return the length of the default keystroke buffer. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000201size_t get_key_buffer_len(void)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000202{
203 return key_buffer_len;
204}
205
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000206/* Add the contents of the keystroke buffer input to the default
207 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000208void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000209{
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000210#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000211 allow_pending_sigwinch(TRUE);
212 allow_pending_sigwinch(FALSE);
213#endif
214
215 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000216 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000217 return;
218
219 /* If adding input would put the default keystroke buffer beyond
220 * maximum capacity, only add enough of input to put it at maximum
221 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000222 if (key_buffer_len + input_len < key_buffer_len)
223 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000224
225 /* Add the length of input to the length of the default keystroke
226 * buffer, and reallocate the default keystroke buffer so that it
227 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000228 key_buffer_len += input_len;
229 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
230 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000231
232 /* If the default keystroke buffer wasn't empty before, move its
233 * beginning forward far enough so that we can add input to its
234 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000235 if (key_buffer_len > input_len)
236 memmove(key_buffer + input_len, key_buffer,
237 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000238
239 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000240 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000241}
242
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000243/* Put back the character stored in kbinput, putting it in byte range
244 * beforehand. If meta_key is TRUE, put back the Escape character after
245 * putting back kbinput. If func_key is TRUE, put back the function key
246 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000247void unget_kbinput(int kbinput, bool meta_key, bool func_key)
248{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000249 if (!func_key)
250 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000251
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000252 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000253
254 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000255 kbinput = NANO_CONTROL_3;
256 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000257 }
258}
259
260/* Try to read input_len characters from the default keystroke buffer.
261 * If the default keystroke buffer is empty and win isn't NULL, try to
262 * read in more characters from win and add them to the default
263 * keystroke buffer before doing anything else. If the default
264 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000265int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000266{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000267 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000268
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000269#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000270 allow_pending_sigwinch(TRUE);
271 allow_pending_sigwinch(FALSE);
272#endif
273
274 if (key_buffer_len == 0) {
275 if (win != NULL)
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000276 get_key_buffer(win);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000277
278 if (key_buffer_len == 0)
279 return NULL;
280 }
281
282 /* If input_len is greater than the length of the default keystroke
283 * buffer, only read the number of characters in the default
284 * keystroke buffer. */
285 if (input_len > key_buffer_len)
286 input_len = key_buffer_len;
287
288 /* Subtract input_len from the length of the default keystroke
289 * buffer, and allocate the keystroke buffer input so that it
290 * has enough room for input_len keystrokes. */
291 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000292 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000293
294 /* Copy input_len characters from the beginning of the default
295 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000296 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000297
298 /* If the default keystroke buffer is empty, mark it as such. */
299 if (key_buffer_len == 0) {
300 free(key_buffer);
301 key_buffer = NULL;
302 /* If the default keystroke buffer isn't empty, move its
David Lawrence Ramsey1c367b62005-09-04 03:29:47 +0000303 * beginning forward far enough so that the keystrokes in input are
304 * no longer at its beginning. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000305 } else {
306 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000307 sizeof(int));
308 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
309 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000310 }
311
312 return input;
313}
314
315/* Read in a single character. If it's ignored, swallow it and go on.
316 * Otherwise, try to translate it from ASCII, meta key sequences, escape
317 * sequences, and/or extended keypad values. Set meta_key to TRUE when
318 * we get a meta key sequence, and set func_key to TRUE when we get an
319 * extended keypad value. Supported extended keypad values consist of
320 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
321 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
322 * the function keypad (F1-F16), and the numeric keypad with NumLock
323 * off. Assume nodelay(win) is FALSE. */
324int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
325{
326 int kbinput;
327
328 /* Read in a character and interpret it. Continue doing this until
329 * we get a recognized value or sequence. */
330 while ((kbinput = parse_kbinput(win, meta_key, func_key
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000331#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000332 , FALSE
333#endif
334 )) == ERR);
335
336 return kbinput;
337}
338
339/* Translate ASCII characters, extended keypad values, and escape
340 * sequences into their corresponding key values. Set meta_key to TRUE
341 * when we get a meta key sequence, and set func_key to TRUE when we get
342 * a function key. Assume nodelay(win) is FALSE. */
343int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000344#ifndef NANO_TINY
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000345 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000346#endif
347 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000348
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000349{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000350 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000351 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000352
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000353#ifndef NANO_TINY
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000354 if (reset) {
355 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000356 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000357 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000358 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000359#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000360
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000361 *meta_key = FALSE;
362 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000363
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000364 /* Read in a character. */
365 while ((kbinput = get_input(win, 1)) == NULL);
366
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000367 switch (*kbinput) {
368 case ERR:
369 break;
370 case NANO_CONTROL_3:
371 /* Increment the escape counter. */
372 escapes++;
373 switch (escapes) {
374 case 1:
375 /* One escape: wait for more input. */
376 case 2:
377 /* Two escapes: wait for more input. */
378 break;
379 default:
380 /* More than two escapes: reset the escape counter
381 * and wait for more input. */
382 escapes = 0;
383 }
384 break;
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000385#if !defined(NANO_TINY) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000386 /* Since we don't change the default SIGWINCH handler when
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000387 * NANO_TINY is defined, KEY_RESIZE is never generated. Also,
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000388 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
389 case KEY_RESIZE:
390 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000391#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000392#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000393 case KEY_SHIFT_L:
394 case KEY_SHIFT_R:
395 case KEY_CONTROL_L:
396 case KEY_CONTROL_R:
397 case KEY_ALT_L:
398 case KEY_ALT_R:
399 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000400#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000401 default:
402 switch (escapes) {
403 case 0:
404 switch (*kbinput) {
405 case NANO_CONTROL_8:
406 retval = ISSET(REBIND_DELETE) ?
407 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
408 break;
409 case KEY_DOWN:
410 retval = NANO_NEXTLINE_KEY;
411 break;
412 case KEY_UP:
413 retval = NANO_PREVLINE_KEY;
414 break;
415 case KEY_LEFT:
416 retval = NANO_BACK_KEY;
417 break;
418 case KEY_RIGHT:
419 retval = NANO_FORWARD_KEY;
420 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000421#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000422 /* HP-UX 10 and 11 don't support KEY_HOME. */
423 case KEY_HOME:
424 retval = NANO_HOME_KEY;
425 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000426#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000427 case KEY_BACKSPACE:
428 retval = NANO_BACKSPACE_KEY;
429 break;
430 case KEY_DC:
431 retval = ISSET(REBIND_DELETE) ?
432 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
433 break;
434 case KEY_IC:
435 retval = NANO_INSERTFILE_KEY;
436 break;
437 case KEY_NPAGE:
438 retval = NANO_NEXTPAGE_KEY;
439 break;
440 case KEY_PPAGE:
441 retval = NANO_PREVPAGE_KEY;
442 break;
443 case KEY_ENTER:
444 retval = NANO_ENTER_KEY;
445 break;
446 case KEY_A1: /* Home (7) on numeric keypad
447 * with NumLock off. */
448 retval = NANO_HOME_KEY;
449 break;
450 case KEY_A3: /* PageUp (9) on numeric keypad
451 * with NumLock off. */
452 retval = NANO_PREVPAGE_KEY;
453 break;
454 case KEY_B2: /* Center (5) on numeric keypad
455 * with NumLock off. */
456 break;
457 case KEY_C1: /* End (1) on numeric keypad
458 * with NumLock off. */
459 retval = NANO_END_KEY;
460 break;
461 case KEY_C3: /* PageDown (4) on numeric
462 * keypad with NumLock off. */
463 retval = NANO_NEXTPAGE_KEY;
464 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000465#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000466 /* Slang doesn't support KEY_BEG. */
467 case KEY_BEG: /* Center (5) on numeric keypad
468 * with NumLock off. */
469 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000470#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000471#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000472 /* HP-UX 10 and 11 don't support KEY_END. */
473 case KEY_END:
474 retval = NANO_END_KEY;
475 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000476#endif
David Lawrence Ramsey475c4022006-01-30 01:32:41 +0000477#ifdef KEY_SBEG
478 /* Slang doesn't support KEY_SBEG. */
479 case KEY_SBEG: /* Center (5) on numeric keypad
480 * with NumLock off. */
481 break;
482#endif
483#ifdef KEY_SDC
484 /* Slang doesn't support KEY_SDC. */
485 case KEY_SDC:
David Lawrence Ramsey3a5e6f92006-01-30 21:23:51 +0000486 retval = ISSET(REBIND_DELETE) ?
487 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
David Lawrence Ramsey475c4022006-01-30 01:32:41 +0000488 break;
489#endif
490#ifdef KEY_SEND
491 /* HP-UX 10 and 11 don't support KEY_SEND. */
492 case KEY_SEND:
493 retval = NANO_END_KEY;
494 break;
495#endif
496#ifdef KEY_SHOME
497 /* HP-UX 10 and 11 and Slang don't support
498 * KEY_SHOME. */
499 case KEY_SHOME:
500 retval = NANO_HOME_KEY;
501 break;
502#endif
503#ifdef KEY_SIC
504 /* Slang doesn't support KEY_SIC. */
505 case KEY_SIC:
506 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000507 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000508#endif
509#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000510 /* Slang doesn't support KEY_SLEFT. */
511 case KEY_SLEFT:
512 retval = NANO_BACK_KEY;
513 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000514#endif
515#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000516 /* Slang doesn't support KEY_SRIGHT. */
517 case KEY_SRIGHT:
518 retval = NANO_FORWARD_KEY;
519 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000520#endif
David Lawrence Ramsey475c4022006-01-30 01:32:41 +0000521#ifdef KEY_SSUSPEND
522 /* Slang doesn't support KEY_SSUSPEND. */
523 case KEY_SSUSPEND:
524 retval = NANO_SUSPEND_KEY;
525 break;
526#endif
527#ifdef KEY_SUSPEND
528 /* Slang doesn't support KEY_SUSPEND. */
529 case KEY_SUSPEND:
530 retval = NANO_SUSPEND_KEY;
531 break;
532#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000533 default:
534 retval = *kbinput;
535 break;
536 }
537 break;
538 case 1:
539 /* One escape followed by a non-escape: escape
540 * sequence mode. Reset the escape counter. If
541 * there aren't any other keys waiting, we have a
542 * meta key sequence, so set meta_key to TRUE and
543 * save the lowercase version of the non-escape
544 * character as the result. If there are other keys
545 * waiting, we have a true escape sequence, so
546 * interpret it. */
547 escapes = 0;
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000548 if (get_key_buffer_len() == 0) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000549 *meta_key = TRUE;
550 retval = tolower(*kbinput);
551 } else {
552 int *seq;
553 size_t seq_len;
554 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000555
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000556 /* Put back the non-escape character, get the
557 * complete escape sequence, translate the
558 * sequence into its corresponding key value,
559 * and save that as the result. */
560 unget_input(kbinput, 1);
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000561 seq_len = get_key_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000562 seq = get_input(NULL, seq_len);
563 retval = get_escape_seq_kbinput(seq, seq_len,
564 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000565
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000566 /* If the escape sequence is unrecognized and
567 * not ignored, put back all of its characters
568 * except for the initial escape. */
569 if (retval == ERR && !ignore_seq)
570 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000571
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000572 free(seq);
573 }
574 break;
575 case 2:
576 /* Two escapes followed by one or more decimal
David Lawrence Ramsey38f70a52005-07-19 18:46:02 +0000577 * digits: byte sequence mode. If the byte
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000578 * sequence's range is limited to 2XX (the first
579 * digit is in the '0' to '2' range and it's the
580 * first digit, or it's in the '0' to '9' range and
581 * it's not the first digit), increment the byte
582 * sequence counter and interpret the digit. If the
583 * byte sequence's range is not limited to 2XX, fall
584 * through. */
585 if (('0' <= *kbinput && *kbinput <= '6' &&
586 byte_digits == 0) || ('0' <= *kbinput &&
587 *kbinput <= '9' && byte_digits > 0)) {
588 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000589
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000590 byte_digits++;
591 byte = get_byte_kbinput(*kbinput
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000592#ifndef NANO_TINY
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000593 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000594#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000595 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000596
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000597 if (byte != ERR) {
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000598 char *byte_mb;
599 int byte_mb_len, *seq, i;
600
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000601 /* If we've read in a complete byte
602 * sequence, reset the byte sequence counter
603 * and the escape counter, and put back the
604 * corresponding byte value. */
605 byte_digits = 0;
606 escapes = 0;
607
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000608 /* Put back the multibyte equivalent of the
609 * byte value. */
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +0000610 byte_mb = make_mbchar((long)byte,
611 &byte_mb_len);
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000612
613 seq = (int *)nmalloc(byte_mb_len *
614 sizeof(int));
615
616 for (i = 0; i < byte_mb_len; i++)
617 seq[i] = (unsigned char)byte_mb[i];
618
619 unget_input(seq, byte_mb_len);
620
621 free(byte_mb);
622 free(seq);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000623 }
624 } else {
625 /* Reset the escape counter. */
626 escapes = 0;
627 if (byte_digits == 0)
628 /* Two escapes followed by a non-decimal
629 * digit or a decimal digit that would
630 * create a byte sequence greater than 2XX,
631 * and we're not in the middle of a byte
632 * sequence: control character sequence
633 * mode. Interpret the control sequence and
634 * save the corresponding control character
635 * as the result. */
636 retval = get_control_kbinput(*kbinput);
637 else {
638 /* If we're in the middle of a byte
639 * sequence, reset the byte sequence counter
640 * and save the character we got as the
641 * result. */
642 byte_digits = 0;
643 retval = *kbinput;
644 }
645 }
646 break;
647 }
648 }
649
650 /* If we have a result and it's an extended keypad value (i.e, a
651 * value outside of byte range), set func_key to TRUE. */
652 if (retval != ERR)
653 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000654
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000655#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000656 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 +0000657#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000658
659 /* Return the result. */
660 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000661}
662
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000663/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000664 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000665 * are generated when the keypad doesn't support the needed keys. If
666 * the escape sequence is recognized but we want to ignore it, return
667 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
668 * set ignore_seq to FALSE. Assume that Escape has already been read
669 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000670int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000671 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000672{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000673 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000674
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000675 *ignore_seq = FALSE;
676
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000677 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000678 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000679 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000680 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000681 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000682 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000683 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000684 case 'P': /* Esc O 2 P == F13 on
685 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000686 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000687 break;
688 case 'Q': /* Esc O 2 Q == F14 on
689 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000690 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000691 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000692 case 'R': /* Esc O 2 R == F15 on
693 * xterm. */
694 retval = KEY_F(15);
695 break;
696 case 'S': /* Esc O 2 S == F16 on
697 * xterm. */
698 retval = KEY_F(16);
699 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000700 }
701 }
702 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000703 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
704 case 'B': /* Esc O B == Down on
705 * VT100/VT320/xterm. */
706 case 'C': /* Esc O C == Right on
707 * VT100/VT320/xterm. */
708 case 'D': /* Esc O D == Left on
709 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000710 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000711 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000712 case 'E': /* Esc O E == Center (5) on numeric keypad
713 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000714 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000715 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000716 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000717 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000718 break;
719 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000720 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000721 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000722 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000723 * NumLock off on VT100/VT220/VT320/xterm/
724 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000725 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000726 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000727 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000728 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000729 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000730 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000731 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000732 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000733 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000734 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000735 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000736 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000737 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000738 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000739 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000740 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000741 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000742 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000743 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000744 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000745 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000746 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000747 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000748 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000749 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000750 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000751 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000752 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000753 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000754 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000755 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000756 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000757 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000758 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000759 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000760 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000761 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000762 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000763 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000764 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000765 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000766 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000767 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000768 * NumLock off on VT100/VT220/VT320/xterm/
769 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000770 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000771 break;
772 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000773 * NumLock off on VT100/VT220/VT320/xterm/
774 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000775 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000776 break;
777 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000778 * NumLock off on VT100/VT220/VT320/xterm/
779 * rxvt. */
David Lawrence Ramsey8f36d092005-09-24 19:42:48 +0000780 retval = ',';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000781 break;
782 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000783 * NumLock off on VT100/VT220/VT320/xterm/
784 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000785 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000786 break;
787 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000788 * with NumLock off on VT100/VT220/VT320/
789 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000790 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000791 break;
792 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000793 * NumLock off on VT100/VT220/VT320/xterm/
794 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000795 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000796 break;
797 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000798 * with NumLock off on VT100/VT220/VT320/
799 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000800 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000801 break;
802 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000803 * with NumLock off on VT100/VT220/VT320/
804 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000805 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000806 break;
807 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000808 * with NumLock off on VT100/VT220/VT320/
809 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000810 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000811 break;
812 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000813 * keypad with NumLock off on VT100/VT220/
814 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000815 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000816 break;
817 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000818 * with NumLock off on VT100/VT220/VT320/
819 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000820 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000821 break;
822 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000823 * with NumLock off on VT100/VT220/VT320/
824 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000825 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000826 break;
827 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000828 * with NumLock off on VT100/VT220/VT320/
829 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000830 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000831 break;
832 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000833 * with NumLock off on VT100/VT220/VT320/
834 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000835 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000836 break;
837 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000838 * with NumLock off on VT100/VT220/VT320/
839 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000840 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000841 break;
842 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000843 * with NumLock off on VT100/VT220/VT320/
844 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000845 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000846 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000847 }
848 break;
849 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000850 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000851 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000852 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000853 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000854 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000855 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000856 break;
857 }
858 break;
859 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000860 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000861 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000862 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000863 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000864 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
865 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000866 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000867 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000868 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
869 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000870 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000871 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000872 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
873 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000874 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000875 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000876 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
877 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000878 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000879 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000880 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
881 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000882 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000883 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000884 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000885 * VT220/VT320/Linux console/
886 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000887 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000888 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000889 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000890 * VT220/VT320/Linux console/
891 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000892 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000893 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000894 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000895 * VT220/VT320/Linux console/
896 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000897 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000898 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000899 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000900 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000901 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000902 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000903 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000904 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000905 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
906 * xterm. */
907 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
908 * xterm. */
909 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
910 * xterm. */
911 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
912 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000913 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000914 break;
915 }
916 }
917 break;
918 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000919 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000920 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000921 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
922 * xterm. */
923 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
924 * xterm. */
925 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
926 * xterm. */
927 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
928 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000929 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000930 break;
931 }
932 }
933 break;
934 }
935 }
936 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000937 default: /* Esc [ 1 ~ == Home on
938 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000939 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000940 break;
941 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000942 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000943 break;
944 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000945 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000946 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000947 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000948 * VT220/VT320/Linux console/
949 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000950 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000951 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000952 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000953 * VT220/VT320/Linux console/
954 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000955 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000956 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000957 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000958 * VT220/VT320/Linux console/
959 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000960 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000961 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000962 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000963 * VT220/VT320/Linux console/
964 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000965 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000966 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000967 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000968 * VT220/VT320/Linux console/
969 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000970 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000971 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000972 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000973 * VT220/VT320/Linux console/
974 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000975 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000976 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000977 case '8': /* Esc [ 2 8 ~ == F15 on
978 * VT220/VT320/Linux console/
979 * rxvt/Eterm. */
980 retval = KEY_F(15);
981 break;
982 case '9': /* Esc [ 2 9 ~ == F16 on
983 * VT220/VT320/Linux console/
984 * rxvt/Eterm. */
985 retval = KEY_F(16);
986 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000987 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000988 * VT220/VT320/Linux console/
989 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000990 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000991 break;
992 }
993 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000994 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000995 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
996 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000997 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000998 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000999 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001000 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001001 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001002 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001003 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
1004 * Linux console/xterm; Esc [ 5 ^ ==
1005 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001006 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001007 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001008 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
1009 * Linux console/xterm; Esc [ 6 ^ ==
1010 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001011 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001012 break;
1013 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001014 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001015 break;
1016 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001017 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001018 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001019 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001020 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001021 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001022 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001023 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001024 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001025 case 'A': /* Esc [ A == Up 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 'B': /* Esc [ B == Down 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 Ramsey0381c212004-05-01 01:21:38 +00001031 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001032 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001033 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001034 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001035 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001036 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001037 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001038 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001039 case 'E': /* Esc [ E == Center (5) on numeric keypad
1040 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +00001041 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001042 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001043 case 'F': /* Esc [ F == End on FreeBSD
1044 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001045 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001046 break;
1047 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001048 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001049 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001050 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001051 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001052 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001053 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001054 break;
1055 case 'I': /* Esc [ I == PageUp on FreeBSD
1056 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001057 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001058 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001059 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001060 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001062 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001063 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001064 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001065 break;
1066 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001067 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001068 break;
1069 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001070 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001071 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001072 case 'P': /* Esc [ O P == F1 on
1073 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001074 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001075 break;
1076 case 'Q': /* Esc [ O Q == F2 on
1077 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001078 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001079 break;
1080 case 'R': /* Esc [ O R == F3 on
1081 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001082 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001083 break;
1084 case 'S': /* Esc [ O S == F4 on
1085 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001086 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001087 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001088 }
David Lawrence Ramseyec729752005-09-25 18:42:05 +00001089 } else
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001090 /* Esc [ O == F3 on FreeBSD console. */
1091 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001092 break;
1093 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001094 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001095 break;
1096 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001097 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001098 break;
1099 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001100 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001101 break;
1102 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001103 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001104 break;
1105 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001106 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001107 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001108 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001109 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001110 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001111 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001112 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001113 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001114 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001115 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001116 break;
1117 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001118 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001119 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001120 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001121 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001122 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001123 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001124 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001125 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001126 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001127 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001128 case 'c': /* Esc [ c == Shift-Right on rxvt/
1129 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001130 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001131 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001132 break;
1133 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001134 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001135 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001136 case 'A': /* Esc [ [ A == F1 on Linux
1137 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001138 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001139 break;
1140 case 'B': /* Esc [ [ B == F2 on Linux
1141 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001142 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001143 break;
1144 case 'C': /* Esc [ [ C == F3 on Linux
1145 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001146 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001147 break;
1148 case 'D': /* Esc [ [ D == F4 on Linux
1149 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001150 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001151 break;
1152 case 'E': /* Esc [ [ E == F5 on Linux
1153 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001154 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001155 break;
1156 }
1157 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001158 break;
1159 }
1160 break;
1161 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001162 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001163
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001164#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001165 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001166#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001167
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001168 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001169}
1170
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001171/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001172 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001173 * to many escape sequences. */
1174int get_escape_seq_abcd(int kbinput)
1175{
1176 switch (tolower(kbinput)) {
1177 case 'a':
1178 return NANO_PREVLINE_KEY;
1179 case 'b':
1180 return NANO_NEXTLINE_KEY;
1181 case 'c':
1182 return NANO_FORWARD_KEY;
1183 case 'd':
1184 return NANO_BACK_KEY;
1185 default:
1186 return ERR;
1187 }
1188}
1189
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001190/* Translate a byte sequence: turn a three-digit decimal number from
1191 * 000 to 255 into its corresponding byte value. */
1192int get_byte_kbinput(int kbinput
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001193#ifndef NANO_TINY
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001194 , bool reset
1195#endif
1196 )
1197{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001198 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001199 int retval = ERR;
1200
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001201#ifndef NANO_TINY
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001202 if (reset) {
1203 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001204 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001205 return ERR;
1206 }
1207#endif
1208
1209 /* Increment the byte digit counter. */
1210 byte_digits++;
1211
1212 switch (byte_digits) {
1213 case 1:
1214 /* One digit: reset the byte sequence holder and add the
1215 * digit we got to the 100's position of the byte sequence
1216 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001217 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001218 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001219 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001220 else
1221 /* If the character we got isn't a decimal digit, or if
1222 * it is and it would put the byte sequence out of byte
1223 * range, save it as the result. */
1224 retval = kbinput;
1225 break;
1226 case 2:
1227 /* Two digits: add the digit we got to the 10's position of
1228 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001229 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1230 '6' <= kbinput && kbinput <= '9'))
1231 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001232 else
1233 /* If the character we got isn't a decimal digit, or if
1234 * it is and it would put the byte sequence out of byte
1235 * range, save it as the result. */
1236 retval = kbinput;
1237 break;
1238 case 3:
1239 /* Three digits: add the digit we got to the 1's position of
1240 * the byte sequence holder, and save the corresponding word
1241 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001242 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1243 '6' <= kbinput && kbinput <= '9')) {
1244 byte += (kbinput - '0');
1245 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001246 } else
1247 /* If the character we got isn't a decimal digit, or if
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001248 * it is and it would put the byte sequence out of word
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001249 * range, save it as the result. */
1250 retval = kbinput;
1251 break;
1252 default:
1253 /* More than three digits: save the character we got as the
1254 * result. */
1255 retval = kbinput;
1256 break;
1257 }
1258
1259 /* If we have a result, reset the byte digit counter and the byte
1260 * sequence holder. */
1261 if (retval != ERR) {
1262 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001263 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001264 }
1265
1266#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001267 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 +00001268#endif
1269
1270 return retval;
1271}
1272
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001273/* Translate a Unicode sequence: turn a six-digit hexadecimal number
1274 * from 000000 to 10FFFF (case-insensitive) into its corresponding
1275 * multibyte value. */
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001276long get_unicode_kbinput(int kbinput
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001277#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001278 , bool reset
1279#endif
1280 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001281{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001282 static int uni_digits = 0;
1283 static long uni = 0;
1284 long retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001285
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001286#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001287 if (reset) {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001288 uni_digits = 0;
1289 uni = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001290 return ERR;
1291 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001292#endif
1293
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001294 /* Increment the Unicode digit counter. */
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001295 uni_digits++;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001296
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001297 switch (uni_digits) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001298 case 1:
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001299 /* One digit: reset the Unicode sequence holder and add the
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001300 * digit we got to the 0x100000's position of the Unicode
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001301 * sequence holder. */
1302 uni = 0;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001303 if ('0' <= kbinput && kbinput <= '1')
1304 uni += (kbinput - '0') * 0x100000;
1305 else
1306 /* If the character we got isn't a hexadecimal digit, or
1307 * if it is and it would put the Unicode sequence out of
1308 * valid range, save it as the result. */
1309 retval = kbinput;
1310 break;
1311 case 2:
1312 /* Two digits: add the digit we got to the 0x10000's
1313 * position of the Unicode sequence holder. */
1314 if ('0' == kbinput || (uni < 0x100000 && '1' <= kbinput &&
1315 kbinput <= '9'))
1316 uni += (kbinput - '0') * 0x10000;
1317 else if (uni < 0x100000 && 'a' <= tolower(kbinput) &&
1318 tolower(kbinput) <= 'f')
1319 uni += (tolower(kbinput) + 10 - 'a') * 0x10000;
1320 else
1321 /* If the character we got isn't a hexadecimal digit, or
1322 * if it is and it would put the Unicode sequence out of
1323 * valid range, save it as the result. */
1324 retval = kbinput;
1325 break;
1326 case 3:
1327 /* Three digits: add the digit we got to the 0x1000's
1328 * position of the Unicode sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001329 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001330 uni += (kbinput - '0') * 0x1000;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001331 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001332 uni += (tolower(kbinput) + 10 - 'a') * 0x1000;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001333 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001334 /* If the character we got isn't a hexadecimal digit, or
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001335 * if it is and it would put the Unicode sequence out of
1336 * valid range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001337 retval = kbinput;
1338 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001339 case 4:
1340 /* Four digits: add the digit we got to the 0x100's position
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001341 * of the Unicode sequence holder. */
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001342 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001343 uni += (kbinput - '0') * 0x100;
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001344 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001345 uni += (tolower(kbinput) + 10 - 'a') * 0x100;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001346 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001347 /* If the character we got isn't a hexadecimal digit, or
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001348 * if it is and it would put the Unicode sequence out of
1349 * valid range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001350 retval = kbinput;
1351 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001352 case 5:
1353 /* Five digits: add the digit we got to the 0x10's position
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001354 * of the Unicode sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001355 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001356 uni += (kbinput - '0') * 0x10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001357 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001358 uni += (tolower(kbinput) + 10 - 'a') * 0x10;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001359 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001360 /* If the character we got isn't a hexadecimal digit, or
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001361 * if it is and it would put the Unicode sequence out of
1362 * valid range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001363 retval = kbinput;
1364 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001365 case 6:
1366 /* Six digits: add the digit we got to the 1's position of
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001367 * the Unicode sequence holder, and save the corresponding
1368 * Unicode value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001369 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001370 uni += (kbinput - '0');
1371 retval = uni;
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001372 } else if ('a' <= tolower(kbinput) && tolower(kbinput) <=
1373 'f') {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001374 uni += (tolower(kbinput) + 10 - 'a');
1375 retval = uni;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001376 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001377 /* If the character we got isn't a hexadecimal digit, or
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001378 * if it is and it would put the Unicode sequence out of
1379 * valid range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001380 retval = kbinput;
1381 break;
1382 default:
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001383 /* More than six digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001384 * result. */
1385 retval = kbinput;
1386 break;
1387 }
1388
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001389 /* If we have a result, reset the Unicode digit counter and the
1390 * Unicode sequence holder. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001391 if (retval != ERR) {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001392 uni_digits = 0;
1393 uni = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001394 }
1395
1396#ifdef DEBUG
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001397 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 +00001398#endif
1399
1400 return retval;
1401}
1402
1403/* Translate a control character sequence: turn an ASCII non-control
1404 * character into its corresponding control character. */
1405int get_control_kbinput(int kbinput)
1406{
1407 int retval;
1408
1409 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1410 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1411 kbinput == '`')
1412 retval = NANO_CONTROL_SPACE;
1413 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1414 else if ('3' <= kbinput && kbinput <= '7')
1415 retval = kbinput - 24;
1416 /* Ctrl-8 (Ctrl-?) */
1417 else if (kbinput == '8' || kbinput == '?')
1418 retval = NANO_CONTROL_8;
1419 /* Ctrl-A to Ctrl-_ */
1420 else if ('A' <= kbinput && kbinput <= '_')
1421 retval = kbinput - 64;
1422 /* Ctrl-a to Ctrl-~ */
1423 else if ('a' <= kbinput && kbinput <= '~')
1424 retval = kbinput - 96;
1425 else
1426 retval = kbinput;
1427
1428#ifdef DEBUG
1429 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1430#endif
1431
1432 return retval;
1433}
1434
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001435/* Put the output-formatted characters in output back into the default
1436 * keystroke buffer, so that they can be parsed and displayed as output
1437 * again. */
1438void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001439{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001440 int *input;
1441 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001442
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001443 if (output_len == 0)
1444 return;
1445
1446 input = (int *)nmalloc(output_len * sizeof(int));
1447 for (i = 0; i < output_len; i++)
1448 input[i] = (int)output[i];
1449 unget_input(input, output_len);
1450 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001451}
1452
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001453/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001454 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1455int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1456{
1457 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001458
1459 /* Turn off flow control characters if necessary so that we can type
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001460 * them in verbatim, and turn the keypad off if necessary so that we
1461 * don't get extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001462 if (ISSET(PRESERVE))
1463 disable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001464 if (!ISSET(REBIND_KEYPAD))
1465 keypad(win, FALSE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001466
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001467 /* Read in a stream of characters and interpret it if possible. */
1468 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001469
1470 /* Turn flow control characters back on if necessary and turn the
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001471 * keypad back on if necessary now that we're done. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001472 if (ISSET(PRESERVE))
1473 enable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001474 if (!ISSET(REBIND_KEYPAD))
1475 keypad(win, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001476
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001477 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001478}
1479
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001480/* Read in a stream of all available characters, and return the length
1481 * of the string in kbinput_len. Translate the first few characters of
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001482 * the input into the corresponding multibyte value if possible. After
1483 * that, leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001484int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001485{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001486 int *kbinput, *retval;
1487 long uni;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001488
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001489 /* Read in the first keystroke. */
1490 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001491
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001492 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001493 uni = get_unicode_kbinput(*kbinput
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001494#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001495 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001496#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001497 );
1498
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001499 /* If the first keystroke isn't a hexadecimal digit, put back the
1500 * first keystroke. */
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001501 if (uni != ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001502 unget_input(kbinput, 1);
1503 /* Otherwise, read in keystrokes until we have a complete word
1504 * sequence, and put back the corresponding word value. */
1505 else {
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001506 char *uni_mb;
1507 int uni_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001508
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001509 while (uni == ERR) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001510 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001511
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001512 uni = get_unicode_kbinput(*kbinput
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001513#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001514 , FALSE
1515#endif
1516 );
1517 }
1518
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001519 /* Put back the multibyte equivalent of the Unicode value. */
1520 uni_mb = make_mbchar(uni, &uni_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001521
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001522 seq = (int *)nmalloc(uni_mb_len * sizeof(int));
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001523
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001524 for (i = 0; i < uni_mb_len; i++)
1525 seq[i] = (unsigned char)uni_mb[i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001526
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001527 unget_input(seq, uni_mb_len);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001528
1529 free(seq);
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001530 free(uni_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001531 }
1532
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001533 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001534 * result. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00001535 *kbinput_len = get_key_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001536 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001537
1538 return retval;
1539}
1540
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001541#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001542/* Check for a mouse event, and if one's taken place, save the
1543 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001544 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1545 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001546 * place on it, figure out which shortcut was clicked and put back the
1547 * equivalent keystroke(s). Return FALSE if no keystrokes were
1548 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001549 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001550bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001551{
1552 MEVENT mevent;
1553
1554 *mouse_x = -1;
1555 *mouse_y = -1;
1556
1557 /* First, get the actual mouse event. */
1558 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001559 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001560
1561 /* Save the screen coordinates where the mouse event took place. */
1562 *mouse_x = mevent.x;
1563 *mouse_y = mevent.y;
1564
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001565 /* If we're allowing shortcuts, the current shortcut list is being
1566 * displayed on the last two lines of the screen, and the mouse
1567 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001568 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001569 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1570 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001571 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001572 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001573 /* The number of shortcuts in the current shortcut list. */
1574 const shortcut *s = currshortcut;
1575 /* The actual shortcut we clicked on, starting at the first
1576 * one in the current shortcut list. */
1577
1578 /* Get the shortcut lists' length. */
1579 if (currshortcut == main_list)
1580 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001581 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001582 currslen = length_of_list(currshortcut);
1583
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001584 /* We don't show any more shortcuts than the main list
1585 * does. */
1586 if (currslen > MAIN_VISIBLE)
1587 currslen = MAIN_VISIBLE;
1588 }
1589
David Lawrence Ramsey0df61f12005-06-08 20:23:06 +00001590 /* Calculate the width of each shortcut in the list. It's the
1591 * same for all of them. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001592 if (currslen < 2)
1593 i = COLS / 6;
1594 else
1595 i = COLS / ((currslen / 2) + (currslen % 2));
1596
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001597 /* Calculate the y-coordinate relative to the beginning of
David Lawrence Ramseyf7260532005-10-28 17:12:58 +00001598 * the shortcut list in bottomwin, i.e, with the sizes of
1599 * topwin, edit, and the first line of bottomwin subtracted
1600 * out. */
1601 j = *mouse_y - (2 - no_more_space()) - editwinrows - 1;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001602
1603 /* If we're on the statusbar, beyond the end of the shortcut
1604 * list, or beyond the end of a shortcut on the right side of
1605 * the screen, don't do anything. */
1606 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001607 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001608 j = (*mouse_x / i) * 2 + j;
1609 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001610 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001611
1612 /* Go through the shortcut list to determine which shortcut was
1613 * clicked. */
1614 for (; j > 0; j--)
1615 s = s->next;
1616
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001617 /* And put back the equivalent key. Assume that each shortcut
1618 * has, at the very least, an equivalent control key, an
1619 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001620 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001621 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001622 return TRUE;
1623 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001624 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001625 return TRUE;
1626 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001627 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001628 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001629}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001630#endif /* !DISABLE_MOUSE */
1631
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001632/* Return the shortcut corresponding to the values of kbinput (the key
1633 * itself), meta_key (whether the key is a meta sequence), and func_key
1634 * (whether the key is a function key), if any. The shortcut will be
1635 * the first one in the list (control key, meta key sequence, function
1636 * key, other meta key sequence) for the corresponding function. For
1637 * example, passing in a meta key sequence that corresponds to a
1638 * function with a control key, a function key, and a meta key sequence
1639 * will return the control key corresponding to that function. */
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001640const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001641 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001642{
1643 const shortcut *s = s_list;
1644 size_t slen = length_of_list(s_list);
1645
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001646#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001647 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 +00001648#endif
1649
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001650 /* Check for shortcuts. */
1651 for (; slen > 0; slen--) {
1652 /* We've found a shortcut if:
1653 *
1654 * 1. The key exists.
1655 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001656 * 3. meta_key is TRUE and the key is the primary or
1657 * miscellaneous meta sequence in the shortcut list.
1658 * 4. func_key is TRUE and the key is a function key in the
1659 * shortcut list. */
1660
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001661 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1662 (*meta_key == TRUE && (*kbinput == s->metaval ||
1663 *kbinput == s->miscval)) || (*func_key == TRUE &&
1664 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001665 break;
1666 }
1667
1668 s = s->next;
1669 }
1670
1671 /* Translate the shortcut to either its control key or its meta key
1672 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001673 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001674 if (slen > 0) {
1675 if (s->ctrlval != NANO_NO_KEY) {
1676 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001677 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001678 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001679 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001680 } else if (s->metaval != NANO_NO_KEY) {
1681 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001682 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001683 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001684 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001685 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001686 }
1687
1688 return NULL;
1689}
1690
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001691#ifndef NANO_TINY
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001692/* Return the global toggle corresponding to the values of kbinput (the
1693 * key itself) and meta_key (whether the key is a meta sequence), if
1694 * any. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001695const toggle *get_toggle(int kbinput, bool meta_key)
1696{
1697 const toggle *t = toggles;
1698
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001699#ifdef DEBUG
1700 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1701#endif
1702
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001703 /* Check for toggles. */
1704 for (; t != NULL; t = t->next) {
1705 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001706 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001707 if (meta_key && kbinput == t->val)
1708 break;
1709 }
1710
1711 return t;
1712}
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001713#endif /* !NANO_TINY */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001714
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001715/* Move to (x, y) in win, and display a line of n spaces with the
1716 * current attributes. */
1717void blank_line(WINDOW *win, int y, int x, int n)
1718{
1719 wmove(win, y, x);
1720 for (; n > 0; n--)
1721 waddch(win, ' ');
1722}
1723
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001724/* Blank the first line of the top portion of the window. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001725void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001726{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001727 blank_line(topwin, 0, 0, COLS);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001728}
1729
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001730/* If the MORE_SPACE flag isn't set, blank the second line of the top
1731 * portion of the window. */
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00001732void blank_topbar(void)
1733{
1734 if (!ISSET(MORE_SPACE))
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001735 blank_line(topwin, 1, 0, COLS);
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00001736}
1737
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001738/* Blank all the lines of the middle portion of the window, i.e, the
1739 * edit window. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001740void blank_edit(void)
1741{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001742 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001743 for (i = 0; i < editwinrows; i++)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001744 blank_line(edit, i, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001745}
1746
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001747/* Blank the first line of the bottom portion of the window. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001748void blank_statusbar(void)
1749{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001750 blank_line(bottomwin, 0, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001751}
1752
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001753/* If the NO_HELP flag isn't set, blank the last two lines of the bottom
1754 * portion of the window. */
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00001755void blank_bottombars(void)
1756{
1757 if (!ISSET(NO_HELP)) {
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001758 blank_line(bottomwin, 1, 0, COLS);
1759 blank_line(bottomwin, 2, 0, COLS);
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00001760 }
1761}
1762
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001763/* Check if the number of keystrokes needed to blank the statusbar has
1764 * been pressed. If so, blank the statusbar, unless constant cursor
1765 * position display is on. */
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001766void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001767{
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00001768 if (statusblank > 0)
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001769 statusblank--;
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00001770
1771 if (statusblank == 0 && !ISSET(CONST_UPDATE)) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001772 blank_statusbar();
1773 wnoutrefresh(bottomwin);
1774 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00001775 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001776 }
1777}
1778
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001779/* Convert buf into a string that can be displayed on screen. The
1780 * caller wants to display buf starting with column start_col, and
1781 * extending for at most len columns. start_col is zero-based. len is
1782 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001783 * string is dynamically allocated, and should be freed. If dollars is
1784 * TRUE, the caller might put "$" at the beginning or end of the line if
1785 * it's too long. */
1786char *display_string(const char *buf, size_t start_col, size_t len, bool
1787 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001788{
1789 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00001790 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001791 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00001792 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001793 size_t alloc_len;
1794 /* The length of memory allocated for converted. */
1795 char *converted;
1796 /* The string we return. */
1797 size_t index;
1798 /* Current position in converted. */
David Lawrence Ramsey1f104f82006-02-03 03:51:51 +00001799 char *buf_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001800 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001801
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00001802 /* If dollars is TRUE, make room for the "$" at the end of the
1803 * line. */
1804 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
1805 len--;
1806
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001807 if (len == 0)
1808 return mallocstrcpy(NULL, "");
1809
David Lawrence Ramsey1f104f82006-02-03 03:51:51 +00001810 buf_mb = charalloc(mb_cur_max());
1811
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001812 start_index = actual_x(buf, start_col);
1813 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001814
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001815 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001816
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001817 /* Make sure there's enough room for the initial character, whether
1818 * it's a multibyte control character, a non-control multibyte
1819 * character, a tab character, or a null terminator. Rationale:
1820 *
1821 * multibyte control character followed by a null terminator:
1822 * 1 byte ('^') + mb_cur_max() bytes + 1 byte ('\0')
1823 * multibyte non-control character followed by a null terminator:
1824 * mb_cur_max() bytes + 1 byte ('\0')
1825 * tab character followed by a null terminator:
1826 * mb_cur_max() bytes + (tabsize - 1) bytes + 1 byte ('\0')
1827 *
1828 * Since tabsize has a minimum value of 1, it can substitute for 1
1829 * byte above. */
1830 alloc_len = (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
1831 converted = charalloc(alloc_len);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00001832
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001833 index = 0;
1834
David Lawrence Ramsey7f26c732005-09-05 01:36:47 +00001835 if (buf[start_index] != '\t' && (column < start_col || (dollars &&
1836 column > 0))) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001837 /* We don't display all of buf[start_index] since it starts to
1838 * the left of the screen. */
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001839 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001840
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001841 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00001842 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001843 char *ctrl_buf_mb = charalloc(mb_cur_max());
1844 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001845
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001846 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
1847 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00001848
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001849 for (i = 0; i < ctrl_buf_mb_len; i++)
1850 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001851
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001852 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001853
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001854 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00001855
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001856 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001857 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00001858 }
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00001859#ifdef ENABLE_UTF8
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00001860 else if (using_utf8() && mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00001861 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00001862 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001863
1864 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001865 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00001866#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001867 }
1868
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001869 while (buf[start_index] != '\0') {
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001870 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001871
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001872 /* Make sure there's enough room for the next character, whether
1873 * it's a multibyte control character, a non-control multibyte
1874 * character, a tab character, or a null terminator. */
1875 if (index + mb_cur_max() + tabsize + 1 >= alloc_len - 1) {
1876 alloc_len += (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
1877 converted = charealloc(converted, alloc_len);
1878 }
1879
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00001880 /* If buf contains a tab character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001881 if (*buf_mb == '\t') {
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001882#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001883 if (ISSET(WHITESPACE_DISPLAY)) {
1884 int i;
1885
1886 for (i = 0; i < whitespace_len[0]; i++)
1887 converted[index++] = whitespace[i];
1888 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001889#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001890 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001891 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00001892 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001893 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001894 start_col++;
1895 }
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001896 /* If buf contains a control character, interpret it. If buf
David Lawrence Ramsey61f56732005-07-21 22:12:03 +00001897 * contains an invalid multibyte control character, display it
1898 * as such.*/
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001899 } else if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001900 char *ctrl_buf_mb = charalloc(mb_cur_max());
1901 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001902
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001903 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001904 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001905
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001906 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
1907 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001908
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001909 for (i = 0; i < ctrl_buf_mb_len; i++)
1910 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001911
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001912 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001913
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001914 free(ctrl_buf_mb);
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00001915 /* If buf contains a space character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001916 } else if (*buf_mb == ' ') {
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001917#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001918 if (ISSET(WHITESPACE_DISPLAY)) {
1919 int i;
1920
1921 for (i = whitespace_len[0]; i < whitespace_len[0] +
1922 whitespace_len[1]; i++)
1923 converted[index++] = whitespace[i];
1924 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001925#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001926 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001927 start_col++;
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001928 /* If buf contains a non-control character, interpret it. If
1929 * buf contains an invalid multibyte non-control character,
1930 * display it as such. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001931 } else {
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001932 char *nctrl_buf_mb = charalloc(mb_cur_max());
1933 int nctrl_buf_mb_len, i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001934
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001935 nctrl_buf_mb = mbrep(buf_mb, nctrl_buf_mb,
1936 &nctrl_buf_mb_len);
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001937
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001938 for (i = 0; i < nctrl_buf_mb_len; i++)
1939 converted[index++] = nctrl_buf_mb[i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001940
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001941 start_col += mbwidth(nctrl_buf_mb);
1942
1943 free(nctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001944 }
1945
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001946 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001947 }
1948
David Lawrence Ramsey6a0d5b82005-06-13 14:00:22 +00001949 free(buf_mb);
1950
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001951 assert(alloc_len >= index + 1);
1952
1953 /* Null terminate converted. */
1954 converted[index] = '\0';
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00001955
1956 /* Make sure converted takes up no more than len columns. */
1957 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001958 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00001959
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001960 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001961}
1962
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001963/* Display the path specified in path on the titlebar, along with the
1964 * current version of nano and whether the current file has been
1965 * modified. If path is NULL, assume we're in normal editing mode and
1966 * display the current filename instead. Otherwise, assume we're in the
1967 * file browser, and don't display whether the current file has been
1968 * modified. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00001969void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001970{
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001971 int space = COLS;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001972 /* The space we have available for display. */
David Lawrence Ramsey3c43d3d2006-03-30 01:18:29 +00001973 size_t verlen = strlenpt(PACKAGE_STRING) + 1;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001974 /* The length of the version message in columns, plus one for
1975 * padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001976 const char *prefix;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001977 /* "DIR:", "File:", or "New Buffer". Goes before filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001978 size_t prefixlen;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001979 /* The length of the prefix in columns, plus one for padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001980 const char *state;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001981 /* "Modified", "View", or "". Shows the state of this
1982 * buffer. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001983 size_t statelen = 0;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001984 /* The length of the state in columns, or the length of
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00001985 * "Modified" if the state is blank. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001986 char *exppath = NULL;
1987 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001988 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001989 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001990 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001991 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001992
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00001993 assert(path != NULL || openfile->filename != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001994
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00001995 wattron(topwin, reverse_attr);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001996 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001997
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001998 /* space has to be at least 4: two spaces before the version message,
1999 * at least one character of the version message, and one space
2000 * after the version message. */
2001 if (space < 4)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002002 space = 0;
2003 else {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002004 /* Limit verlen to 1/3 the length of the screen in columns,
2005 * minus three columns for spaces. */
2006 if (verlen > (COLS / 3) - 3)
2007 verlen = (COLS / 3) - 3;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002008 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002009
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002010 if (space >= 4) {
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002011 /* Add a space after the version message, and account for both
2012 * it and the two spaces before it. */
David Lawrence Ramsey3c43d3d2006-03-30 01:18:29 +00002013 mvwaddnstr(topwin, 0, 2, PACKAGE_STRING,
2014 actual_x(PACKAGE_STRING, verlen));
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002015 verlen += 3;
2016
2017 /* Account for the full length of the version message. */
2018 space -= verlen;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002019 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002020
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002021#ifndef DISABLE_BROWSER
2022 /* Don't display the state if we're in the file browser. */
2023 if (path != NULL)
2024 state = "";
2025 else
2026#endif
2027 state = openfile->modified ? _("Modified") : ISSET(VIEW_MODE) ?
2028 _("View") : "";
2029
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002030 statelen = strlenpt((state[0] != '\0') ? state : _("Modified"));
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002031
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002032 /* If possible, add a space before state. */
2033 if (space > 0 && statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002034 statelen++;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002035 else
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002036 goto the_end;
2037
2038#ifndef DISABLE_BROWSER
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002039 /* path should be a directory if we're in the file browser. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002040 if (path != NULL)
2041 prefix = _("DIR:");
2042 else
2043#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002044 if (openfile->filename[0] == '\0') {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002045 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002046 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002047 } else
2048 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002049
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002050 prefixlen = strnlenpt(prefix, space - statelen) + 1;
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002051
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002052 /* If newfie is FALSE, add a space after prefix. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002053 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002054 prefixlen++;
2055
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002056 /* If we're not in the file browser, path should be the current
2057 * filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002058 if (path == NULL)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002059 path = openfile->filename;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002060
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002061 /* Account for the full lengths of the prefix and the state. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002062 if (space >= prefixlen + statelen)
2063 space -= prefixlen + statelen;
2064 else
2065 space = 0;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002066 /* space is now the room we have for the filename. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002067
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002068 if (!newfie) {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002069 size_t lenpt = strlenpt(path), start_col;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002070
David Lawrence Ramseya03d9c02005-09-16 17:24:22 +00002071 dots = (lenpt >= space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002072
2073 if (dots) {
2074 start_col = lenpt - space + 3;
2075 space -= 3;
2076 } else
2077 start_col = 0;
2078
2079 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002080 }
2081
2082 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002083 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2084 /* The length of the expanded filename. */
2085
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002086 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002087 mvwaddnstr(topwin, 0, verlen + ((space - exppathlen) / 3),
2088 prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002089 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002090 waddch(topwin, ' ');
2091 waddstr(topwin, exppath);
2092 }
2093 } else {
2094 /* We will say something like "File: ...ename". */
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002095 mvwaddnstr(topwin, 0, verlen - 1, prefix, actual_x(prefix,
2096 prefixlen));
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002097 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002098 goto the_end;
2099 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002100 waddnstr(topwin, "...", space + 3);
2101 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002102 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002103 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002104 }
2105
2106 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002107 free(exppath);
2108
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002109 if (state[0] != '\0') {
David Lawrence Ramsey3d12f0f2005-10-26 23:14:59 +00002110 if (statelen >= COLS - 1)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002111 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
2112 else {
David Lawrence Ramseycaa86592005-07-10 23:57:32 +00002113 assert(COLS - statelen - 1 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002114
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002115 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002116 actual_x(state, statelen));
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002117 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002118 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002119
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002120 wattroff(topwin, reverse_attr);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002121
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002122 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002123 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002124 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002125}
2126
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002127/* Mark the current file as modified if it isn't already, and then
2128 * update the titlebar to display the file's new status. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002129void set_modified(void)
2130{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002131 if (!openfile->modified) {
2132 openfile->modified = TRUE;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002133 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002134 }
2135}
2136
David Lawrence Ramsey5593e202005-06-28 19:49:15 +00002137/* Display a message on the statusbar, and set disable_cursorpos to
2138 * TRUE, so that the message won't be immediately overwritten if
2139 * constant cursor position display is on. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002140void statusbar(const char *msg, ...)
2141{
2142 va_list ap;
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002143 char *bar, *foo;
2144 size_t start_x, foo_len;
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002145#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002146 bool old_whitespace;
2147#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002148
2149 va_start(ap, msg);
2150
2151 /* Curses mode is turned off. If we use wmove() now, it will muck
2152 * up the terminal settings. So we just use vfprintf(). */
2153 if (curses_ended) {
2154 vfprintf(stderr, msg, ap);
2155 va_end(ap);
2156 return;
2157 }
2158
2159 /* Blank out the line. */
2160 blank_statusbar();
2161
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002162#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002163 old_whitespace = ISSET(WHITESPACE_DISPLAY);
2164 UNSET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002165#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002166 bar = charalloc(mb_cur_max() * (COLS - 3));
2167 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
2168 va_end(ap);
2169 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002170#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002171 if (old_whitespace)
2172 SET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002173#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002174 free(bar);
2175 foo_len = strlenpt(foo);
2176 start_x = (COLS - foo_len - 4) / 2;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002177
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002178 wmove(bottomwin, 0, start_x);
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002179 wattron(bottomwin, reverse_attr);
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002180 waddstr(bottomwin, "[ ");
2181 waddstr(bottomwin, foo);
2182 free(foo);
2183 waddstr(bottomwin, " ]");
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002184 wattroff(bottomwin, reverse_attr);
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002185 wnoutrefresh(bottomwin);
2186 reset_cursor();
2187 wnoutrefresh(edit);
2188 /* Leave the cursor at its position in the edit window, not in
2189 * the statusbar. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002190
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002191 disable_cursorpos = TRUE;
David Lawrence Ramseyc6618532005-06-17 22:33:15 +00002192
2193 /* If we're doing quick statusbar blanking, and constant cursor
2194 * position display is off, blank the statusbar after only one
2195 * keystroke. Otherwise, blank it after twenty-five keystrokes,
2196 * as Pico does. */
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002197 statusblank =
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002198#ifndef NANO_TINY
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002199 ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 :
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002200#endif
2201 25;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002202}
2203
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002204/* Display the shortcut list in s on the last two rows of the bottom
2205 * portion of the window. */
Chris Allegretta6232d662002-05-12 19:52:15 +00002206void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002207{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002208 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002209
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002210 if (ISSET(NO_HELP))
2211 return;
2212
Chris Allegretta6232d662002-05-12 19:52:15 +00002213 if (s == main_list) {
2214 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002215
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002216 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002217 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002218 slen = length_of_list(s);
2219
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002220 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002221 if (slen > MAIN_VISIBLE)
2222 slen = MAIN_VISIBLE;
2223 }
2224
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002225 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002226 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002227 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002228
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002229 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002230
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002231 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002232 const char *keystr;
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002233 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002234
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002235 /* Yucky sentinel values that we can't handle a better way. */
2236 if (s->ctrlval == NANO_CONTROL_SPACE)
2237 strcpy(foo, "^ ");
2238 else if (s->ctrlval == NANO_CONTROL_8)
2239 strcpy(foo, "^?");
2240 /* Normal values. Assume that the shortcut has an equivalent
2241 * control key, meta key sequence, or both. */
2242 else if (s->ctrlval != NANO_NO_KEY)
2243 sprintf(foo, "^%c", s->ctrlval + 64);
2244 else if (s->metaval != NANO_NO_KEY)
2245 sprintf(foo, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00002246
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002247 keystr = foo;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002248
2249 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002250 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002251 }
2252
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002253 wnoutrefresh(bottomwin);
2254 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002255 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002256}
2257
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002258/* Write a shortcut key to the help area at the bottom of the window.
2259 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2260 * to write at most len characters, even if len is very small and
2261 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2262 * the whole string! We do not bother padding the entry with blanks. */
2263void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002264{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002265 size_t keystroke_len = strlenpt(keystroke) + 1;
2266
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002267 assert(keystroke != NULL && desc != NULL);
2268
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002269 wattron(bottomwin, reverse_attr);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002270 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002271 wattroff(bottomwin, reverse_attr);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002272
2273 if (len > keystroke_len)
2274 len -= keystroke_len;
2275 else
2276 len = 0;
2277
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002278 if (len > 0) {
2279 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002280 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002281 }
2282}
2283
David Lawrence Ramsey2b9d6a02005-11-01 17:45:31 +00002284/* Reset current_y, based on the position of current, and put the cursor
2285 * in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002286void reset_cursor(void)
2287{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002288 /* If we haven't opened any files yet, put the cursor in the top
2289 * left corner of the edit window and get out. */
David Lawrence Ramseydbcaa3b2005-07-08 20:59:24 +00002290 if (openfile == NULL) {
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002291 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002292 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002293 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002294
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002295 openfile->current_y = openfile->current->lineno -
2296 openfile->edittop->lineno;
2297 if (openfile->current_y < editwinrows) {
David Lawrence Ramseycfffbf72005-11-16 03:14:11 +00002298 size_t xpt = xplustabs();
2299 wmove(edit, openfile->current_y, xpt - get_page_start(xpt));
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002300 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002301}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002302
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002303/* edit_draw() takes care of the job of actually painting a line into
2304 * the edit window. fileptr is the line to be painted, at row line of
2305 * the window. converted is the actual string to be written to the
2306 * window, with tabs and control characters replaced by strings of
2307 * regular characters. start is the column number of the first
2308 * character of this page. That is, the first character of converted
2309 * corresponds to character number actual_x(fileptr->data, start) of the
2310 * line. */
2311void edit_draw(const filestruct *fileptr, const char *converted, int
2312 line, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002313{
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002314#if !defined(NANO_TINY) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002315 size_t startpos = actual_x(fileptr->data, start);
2316 /* The position in fileptr->data of the leftmost character
2317 * that displays at least partially on the window. */
2318 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2319 /* The position in fileptr->data of the first character that is
2320 * completely off the window to the right.
2321 *
2322 * Note that endpos might be beyond the null terminator of the
2323 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002324#endif
2325
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002326 assert(openfile != NULL && fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002327 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002328
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002329 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002330 * just the text that needs it). */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002331 mvwaddstr(edit, line, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002332
Chris Allegretta7dd77682001-12-08 19:52:28 +00002333#ifdef ENABLE_COLOR
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002334 /* If color syntaxes are available and turned on, we need to display
2335 * them. */
2336 if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
2337 const colortype *tmpcolor = openfile->colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002338
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002339 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2340 int x_start;
2341 /* Starting column for mvwaddnstr. Zero-based. */
2342 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002343 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002344 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002345 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002346 /* Index in converted where we paint. */
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002347 regmatch_t startmatch;
2348 /* Match position for start_regex. */
2349 regmatch_t endmatch;
2350 /* Match position for end_regex. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002351
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002352 if (tmpcolor->bright)
2353 wattron(edit, A_BOLD);
2354 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramseyb0e04c02005-12-08 07:24:54 +00002355 /* Two notes about regexec(). A return value of zero means
2356 * that there is a match. Also, rm_eo is the first
2357 * non-matching character after the match. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002358
2359 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002360 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002361 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002362
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002363 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002364 * last match. Even though two matches may overlap, we
2365 * want to ignore them, so that we can highlight
2366 * C-strings correctly. */
2367 while (k < endpos) {
2368 /* Note the fifth parameter to regexec(). It says
2369 * not to match the beginning-of-line character
2370 * unless k is 0. If regexec() returns REG_NOMATCH,
2371 * there are no more matches in the line. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002372 if (regexec(tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002373 &startmatch, (k == 0) ? 0 : REG_NOTBOL) ==
2374 REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002375 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002376 /* Translate the match to the beginning of the
2377 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002378 startmatch.rm_so += k;
2379 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002380 if (startmatch.rm_so == startmatch.rm_eo) {
2381 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002382 statusbar(
2383 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002384 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002385 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002386 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002387 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002388 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002389 x_start = strnlenpt(fileptr->data,
2390 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002391
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002392 index = actual_x(converted, x_start);
2393
2394 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00002395 strnlenpt(fileptr->data,
2396 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002397
2398 assert(0 <= x_start && 0 <= paintlen);
2399
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002400 mvwaddnstr(edit, line, x_start, converted +
2401 index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002402 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002403 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002404 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002405 } else {
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002406 /* This is a multi-line regex. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002407 * First, we have to see if the beginning of the line is
2408 * colored by a start on an earlier line, and an end on
2409 * this line or later.
2410 *
2411 * We find the first line before fileptr matching the
2412 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002413 * end, then go to step two. Otherwise, find the next
2414 * line after start_line matching the end. If that line
2415 * is not before fileptr, then paint the beginning of
2416 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002417 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002418 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002419 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002420 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002421 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002422
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002423 while (start_line != NULL && regexec(tmpcolor->start,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002424 start_line->data, 1, &startmatch, 0) ==
2425 REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002426 /* If there is an end on this line, there is no need
2427 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002428 if (regexec(tmpcolor->end, start_line->data, 0,
2429 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002430 goto step_two;
2431 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002432 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002433 /* No start found, so skip to the next step. */
2434 if (start_line == NULL)
2435 goto step_two;
2436 /* Now start_line is the first line before fileptr
2437 * containing a start match. Is there a start on this
2438 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002439 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002440 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002441 start_col += startmatch.rm_so;
2442 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002443 if (regexec(tmpcolor->end, start_line->data +
2444 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002445 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002446 REG_NOTBOL) == REG_NOMATCH)
2447 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002448 break;
2449 start_col++;
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002450 if (regexec(tmpcolor->start, start_line->data +
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002451 start_col, 1, &startmatch,
2452 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002453 /* No later start on this line. */
2454 goto step_two;
2455 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002456 /* Indeed, there is a start not followed on this line by
2457 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002458
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002459 /* We have already checked that there is no end before
2460 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002461 * the start at all? We don't paint unterminated
2462 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002463 end_line = fileptr;
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002464 while (end_line != NULL && regexec(tmpcolor->end,
2465 end_line->data, 1, &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002466 end_line = end_line->next;
2467
2468 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002469 if (end_line == NULL || (end_line == fileptr &&
2470 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002471 goto step_two;
2472
2473 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00002474 if (end_line != fileptr)
2475 /* If the start of fileptr is on a different line
2476 * from the end, paintlen is -1, meaning that
2477 * everything on the line gets painted. */
2478 paintlen = -1;
2479 else
2480 /* Otherwise, paintlen is the expanded location of
2481 * the end of the match minus the expanded location
2482 * of the beginning of the page. */
2483 paintlen = actual_x(converted,
2484 strnlenpt(fileptr->data, endmatch.rm_eo) -
2485 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002486
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002487 mvwaddnstr(edit, line, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002488
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002489 step_two:
2490 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002491 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002492
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002493 while (start_col < endpos) {
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002494 if (regexec(tmpcolor->start, fileptr->data +
2495 start_col, 1, &startmatch, (start_col == 0) ?
2496 0 : REG_NOTBOL) == REG_NOMATCH || start_col +
2497 startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002498 /* No more starts on this line. */
2499 break;
2500 /* Translate the match to be relative to the
2501 * beginning of the line. */
2502 startmatch.rm_so += start_col;
2503 startmatch.rm_eo += start_col;
2504
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002505 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002506 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002507 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002508 x_start = strnlenpt(fileptr->data,
2509 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002510
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002511 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002512
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002513 if (regexec(tmpcolor->end, fileptr->data +
2514 startmatch.rm_eo, 1, &endmatch,
2515 (startmatch.rm_eo == 0) ? 0 : REG_NOTBOL) ==
2516 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002517 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002518 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002519 endmatch.rm_so += startmatch.rm_eo;
2520 endmatch.rm_eo += startmatch.rm_eo;
2521 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002522 * appear on this page, and is the match more
2523 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002524 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002525 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002526 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00002527 strnlenpt(fileptr->data,
2528 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002529
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002530 assert(0 <= x_start && x_start < COLS);
2531
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002532 mvwaddnstr(edit, line, x_start, converted +
2533 index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002534 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002535 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002536 /* There is no end on this line. But we haven't
2537 * yet looked for one on later lines. */
2538 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002539
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002540 while (end_line != NULL &&
2541 regexec(tmpcolor->end, end_line->data,
2542 0, NULL, 0) == REG_NOMATCH)
2543 end_line = end_line->next;
2544
2545 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002546 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002547
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002548 mvwaddnstr(edit, line, x_start, converted +
2549 index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002550 /* We painted to the end of the line, so
2551 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002552 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002553 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002554 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002555 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002556 }
2557 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002558
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002559 wattroff(edit, A_BOLD);
2560 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002561 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002562 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002563#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002564
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002565#ifndef NANO_TINY
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002566 /* If the mark is on, we need to display it. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002567 if (openfile->mark_set && (fileptr->lineno <=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002568 openfile->mark_begin->lineno || fileptr->lineno <=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002569 openfile->current->lineno) && (fileptr->lineno >=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002570 openfile->mark_begin->lineno || fileptr->lineno >=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002571 openfile->current->lineno)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002572 /* fileptr is at least partially selected. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002573 const filestruct *top;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002574 /* Either current or mark_begin, whichever is first. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002575 size_t top_x;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002576 /* current_x or mark_begin_x, corresponding to top. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002577 const filestruct *bot;
2578 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002579 int x_start;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002580 /* Starting column for mvwaddnstr(). Zero-based. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002581 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002582 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002583 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002584 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002585 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002586
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00002587 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002588
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002589 if (top->lineno < fileptr->lineno || top_x < startpos)
2590 top_x = startpos;
2591 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2592 bot_x = endpos;
2593
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002594 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002595 if (top_x < endpos && bot_x > startpos) {
2596 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002597
2598 /* x_start is the expanded location of the beginning of the
2599 * mark minus the beginning of the page. */
2600 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002601
2602 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002603 /* If the end of the mark is off the page, paintlen is
2604 * -1, meaning that everything on the line gets
2605 * painted. */
2606 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002607 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002608 /* Otherwise, paintlen is the expanded location of the
2609 * end of the mark minus the expanded location of the
2610 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002611 paintlen = strnlenpt(fileptr->data, bot_x) -
2612 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002613
2614 /* If x_start is before the beginning of the page, shift
2615 * paintlen x_start characters to compensate, and put
2616 * x_start at the beginning of the page. */
2617 if (x_start < 0) {
2618 paintlen += x_start;
2619 x_start = 0;
2620 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002621
2622 assert(x_start >= 0 && x_start <= strlen(converted));
2623
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002624 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002625
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002626 if (paintlen > 0)
2627 paintlen = actual_x(converted + index, paintlen);
2628
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002629 wattron(edit, reverse_attr);
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002630 mvwaddnstr(edit, line, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00002631 paintlen);
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002632 wattroff(edit, reverse_attr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002633 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002634 }
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002635#endif /* !NANO_TINY */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002636}
2637
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002638/* Just update one line in the edit buffer. This is basically a wrapper
David Lawrence Ramseyb3c6b402005-11-07 06:20:02 +00002639 * for edit_draw(). The line will be displayed starting with
2640 * fileptr->data[index]. Likely arguments are current_x or zero. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002641void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002642{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002643 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002644 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002645 char *converted;
2646 /* fileptr->data converted to have tabs and control characters
2647 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002648 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002649
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002650 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002651
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002652 line = fileptr->lineno - openfile->edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002653
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002654 /* We assume the line numbers are valid. Is that really true? */
2655 assert(line < 0 || line == check_linenumbers(fileptr));
2656
2657 if (line < 0 || line >= editwinrows)
2658 return;
2659
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002660 /* First, blank out the line. */
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002661 blank_line(edit, line, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002662
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002663 /* Next, convert variables that index the line to their equivalent
2664 * positions in the expanded line. */
David Lawrence Ramseyb3c6b402005-11-07 06:20:02 +00002665 index = strnlenpt(fileptr->data, index);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002666 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002667
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002668 /* Expand the line, replacing tabs with spaces, and control
2669 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002670 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00002671
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002672 /* Paint the line. */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002673 edit_draw(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002674 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002675
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002676 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002677 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002678 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002679 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002680}
2681
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002682/* Return TRUE if we need an update after moving horizontally, and FALSE
2683 * otherwise. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002684 * placewewant are on different pages. */
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002685bool need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002686{
2687 return
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002688#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002689 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002690#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002691 get_page_start(old_pww) !=
2692 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002693}
2694
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002695/* Return TRUE if we need an update after moving vertically, and FALSE
2696 * otherwise. We need one if the mark is on or if old_pww and
2697 * placewewant are on different pages. */
2698bool need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002699{
2700 return
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002701#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002702 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002703#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002704 get_page_start(old_pww) !=
2705 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002706}
2707
2708/* Scroll the edit window in the given direction and the given number
2709 * of lines, and draw new lines on the blank lines left after the
2710 * scrolling. direction is the direction to scroll, either UP or DOWN,
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002711 * and nlines is the number of lines to scroll. We change edittop, and
David Lawrence Ramsey6969c992005-07-26 00:42:48 +00002712 * assume that current and current_x are up to date. We also assume
2713 * that scrollok(edit) is FALSE. */
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002714void edit_scroll(scroll_dir direction, ssize_t nlines)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002715{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002716 bool do_redraw = need_vertical_update(0);
David Lawrence Ramsey443a7662005-07-14 23:06:22 +00002717 const filestruct *foo;
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002718 ssize_t i;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002719
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002720 /* Don't bother scrolling less than one line. */
2721 if (nlines < 1)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002722 return;
2723
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002724 /* Part 1: nlines is the number of lines we're going to scroll the
2725 * text of the edit window. */
2726
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002727 /* Move the top line of the edit window up or down (depending on the
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002728 * value of direction) nlines lines, or as many lines as we can if
2729 * there are fewer than nlines lines available. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002730 for (i = nlines; i > 0; i--) {
2731 if (direction == UP) {
David Lawrence Ramseye99223d2005-11-10 04:27:30 +00002732 if (openfile->edittop == openfile->fileage)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002733 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002734 openfile->edittop = openfile->edittop->prev;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002735 } else {
David Lawrence Ramseye99223d2005-11-10 04:27:30 +00002736 if (openfile->edittop == openfile->filebot)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002737 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002738 openfile->edittop = openfile->edittop->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002739 }
2740 }
2741
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00002742 /* Limit nlines to the number of lines we could scroll. */
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00002743 nlines -= i;
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00002744
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00002745 /* Don't bother scrolling zero lines or more than the number of
2746 * lines in the edit window minus one; in both cases, get out, and
2747 * in the latter case, call edit_refresh() beforehand. */
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00002748 if (nlines == 0)
2749 return;
2750
2751 if (nlines >= editwinrows) {
2752 edit_refresh();
2753 return;
2754 }
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002755
2756 /* Scroll the text of the edit window up or down nlines lines,
2757 * depending on the value of direction. */
David Lawrence Ramsey47bb8882005-07-22 22:56:03 +00002758 scrollok(edit, TRUE);
2759 wscrl(edit, (direction == UP) ? -nlines : nlines);
2760 scrollok(edit, FALSE);
2761
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002762 /* Part 2: nlines is the number of lines in the scrolled region of
2763 * the edit window that we need to draw. */
2764
David Lawrence Ramsey68346502005-08-16 03:03:15 +00002765 /* If the top or bottom line of the file is now visible in the edit
2766 * window, we need to draw the entire edit window. */
2767 if ((direction == UP && openfile->edittop == openfile->fileage) ||
2768 (direction == DOWN && openfile->edittop->lineno + editwinrows -
2769 1 >= openfile->filebot->lineno))
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00002770 nlines = editwinrows;
David Lawrence Ramseya7f488b2005-07-17 02:19:47 +00002771
David Lawrence Ramseya6eb8482006-01-10 07:51:49 +00002772 /* If the scrolled region contains only one line, and the line
2773 * before it is visible in the edit window, we need to draw it too.
2774 * If the scrolled region contains more than one line, and the lines
2775 * before and after the scrolled region are visible in the edit
2776 * window, we need to draw them too. */
2777 nlines += (nlines == 1) ? 1 : 2;
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00002778
David Lawrence Ramseyde0c5eb2005-07-17 22:51:44 +00002779 if (nlines > editwinrows)
2780 nlines = editwinrows;
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002781
2782 /* If we scrolled up, we're on the line before the scrolled
2783 * region. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002784 foo = openfile->edittop;
David Lawrence Ramsey14588912005-07-14 20:37:01 +00002785
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002786 /* If we scrolled down, move down to the line before the scrolled
2787 * region. */
David Lawrence Ramsey14588912005-07-14 20:37:01 +00002788 if (direction == DOWN) {
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002789 for (i = editwinrows - nlines; i > 0 && foo != NULL; i--)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002790 foo = foo->next;
2791 }
2792
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002793 /* Draw new lines on any blank lines before or inside the scrolled
2794 * region. If we scrolled down and we're on the top line, or if we
2795 * scrolled up and we're on the bottom line, the line won't be
2796 * blank, so we don't need to draw it unless the mark is on or we're
2797 * not on the first page. */
2798 for (i = nlines; i > 0 && foo != NULL; i--) {
2799 if ((i == nlines && direction == DOWN) || (i == 1 &&
2800 direction == UP)) {
2801 if (do_redraw)
2802 update_line(foo, (foo == openfile->current) ?
2803 openfile->current_x : 0);
2804 } else
2805 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002806 openfile->current_x : 0);
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00002807 foo = foo->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002808 }
2809}
2810
2811/* Update any lines between old_current and current that need to be
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00002812 * updated. Use this if we've moved without changing any text. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002813void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002814{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002815 bool do_redraw = need_vertical_update(0) ||
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00002816 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002817 const filestruct *foo;
2818
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002819 /* If either old_current or current is offscreen, scroll the edit
2820 * window until it's onscreen and get out. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002821 if (old_current->lineno < openfile->edittop->lineno ||
2822 old_current->lineno >= openfile->edittop->lineno +
2823 editwinrows || openfile->current->lineno <
2824 openfile->edittop->lineno || openfile->current->lineno >=
2825 openfile->edittop->lineno + editwinrows) {
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002826 filestruct *old_edittop = openfile->edittop;
2827 ssize_t nlines;
2828
2829 /* Put edittop in range of current, get the difference in lines
2830 * between the original edittop and the current edittop, and
2831 * then restore the original edittop. */
2832 edit_update(
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002833#ifndef NANO_TINY
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002834 ISSET(SMOOTH_SCROLL) ? NONE :
2835#endif
2836 CENTER);
2837
2838 nlines = openfile->edittop->lineno - old_edittop->lineno;
2839
2840 openfile->edittop = old_edittop;
2841
David Lawrence Ramseya6eb8482006-01-10 07:51:49 +00002842 /* Update old_current if we're not on the first page and/or
2843 * we're not on the same page as before. */
2844 if (do_redraw)
2845 update_line(old_current, 0);
2846
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00002847 /* Scroll the edit window up or down until edittop is in range
2848 * of current. */
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002849 if (nlines < 0)
2850 edit_scroll(UP, -nlines);
2851 else
2852 edit_scroll(DOWN, nlines);
2853
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002854 return;
2855 }
2856
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00002857 /* Update old_current and current if we're not on the first page
2858 * and/or we're not on the same page as before. If the mark is on,
2859 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002860 foo = old_current;
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00002861
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002862 while (foo != openfile->current) {
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002863 if (do_redraw)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002864 update_line(foo, 0);
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00002865
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002866#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002867 if (!openfile->mark_set)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002868#endif
2869 break;
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00002870
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002871#ifndef NANO_TINY
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00002872 foo = (foo->lineno > openfile->current->lineno) ? foo->prev :
2873 foo->next;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002874#endif
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002875 }
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00002876
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002877 if (do_redraw)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002878 update_line(openfile->current, openfile->current_x);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002879}
2880
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00002881/* Refresh the screen without changing the position of lines. Use this
2882 * if we've moved and changed text. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002883void edit_refresh(void)
2884{
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002885 const filestruct *foo;
2886 int nlines;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002887
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002888 if (openfile->current->lineno < openfile->edittop->lineno ||
2889 openfile->current->lineno >= openfile->edittop->lineno +
2890 editwinrows)
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002891 /* Put the top line of the edit window in range of the current
2892 * line. */
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002893 edit_update(
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002894#ifndef NANO_TINY
David Lawrence Ramseyb2b69762005-06-16 02:13:10 +00002895 ISSET(SMOOTH_SCROLL) ? NONE :
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002896#endif
2897 CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002898
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002899 foo = openfile->edittop;
2900
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002901#ifdef DEBUG
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002902 fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", (long)openfile->edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002903#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002904
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002905 for (nlines = 0; nlines < editwinrows && foo != NULL; nlines++) {
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002906 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002907 openfile->current_x : 0);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002908 foo = foo->next;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002909 }
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002910
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002911 for (; nlines < editwinrows; nlines++)
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002912 blank_line(edit, nlines, 0, COLS);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002913
2914 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002915 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002916}
2917
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002918/* Move edittop to put it in range of current, keeping current in the
2919 * same place. location determines how we move it: if it's CENTER, we
2920 * center current, and if it's NONE, we put current current_y lines
2921 * below edittop. */
David Lawrence Ramseybf0e47d2005-08-01 18:27:10 +00002922void edit_update(update_type location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002923{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002924 filestruct *foo = openfile->current;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002925 int goal;
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00002926
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002927 /* If location is CENTER, we move edittop up (editwinrows / 2)
2928 * lines. This puts current at the center of the screen. If
2929 * location is NONE, we move edittop up current_y lines if current_y
2930 * is in range of the screen, 0 lines if current_y is less than 0,
2931 * or (editwinrows - 1) lines if current_y is greater than
2932 * (editwinrows - 1). This puts current at the same place on the
2933 * screen as before, or at the top or bottom of the screen if
2934 * edittop is beyond either. */
2935 if (location == CENTER)
2936 goal = editwinrows / 2;
2937 else {
2938 goal = openfile->current_y;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002939
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002940 /* Limit goal to (editwinrows - 1) lines maximum. */
2941 if (goal > editwinrows - 1)
2942 goal = editwinrows - 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002943 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002944
David Lawrence Ramseyb885c9c2005-11-10 05:20:25 +00002945 for (; goal > 0 && foo->prev != NULL; goal--)
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002946 foo = foo->prev;
2947
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002948 openfile->edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002949}
2950
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002951/* Unconditionally redraw the entire screen. */
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00002952void total_redraw(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002953{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002954#ifdef USE_SLANG
2955 /* Slang curses emulation brain damage, part 3: Slang doesn't define
2956 * curscr. */
2957 SLsmg_touch_screen();
2958 SLsmg_refresh();
2959#else
2960 wrefresh(curscr);
2961#endif
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002962}
2963
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002964/* Unconditionally redraw the entire screen, and then refresh it using
2965 * the current file. */
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002966void total_refresh(void)
2967{
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00002968 total_redraw();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002969 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00002970 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002971 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002972}
2973
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002974/* Display the main shortcut list on the last two rows of the bottom
2975 * portion of the window. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002976void display_main_list(void)
2977{
2978 bottombars(main_list);
2979}
2980
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00002981/* If constant is TRUE, we display the current cursor position only if
2982 * disable_cursorpos is FALSE. Otherwise, we display it
2983 * unconditionally and set disable_cursorpos to FALSE. If constant is
2984 * TRUE and disable_cursorpos is TRUE, we also set disable_cursorpos to
2985 * FALSE, so that we leave the current statusbar alone this time, and
2986 * display the current cursor position next time. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00002987void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002988{
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00002989 filestruct *f;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00002990 char c;
David Lawrence Ramsey5745c0a2005-07-31 20:20:37 +00002991 size_t i, cur_xpt = xplustabs() + 1;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002992 size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00002993 int linepct, colpct, charpct;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002994
David Lawrence Ramsey4ab80152005-07-31 18:51:51 +00002995 assert(openfile->fileage != NULL && openfile->current != NULL);
Chris Allegretta2084acc2001-11-29 03:43:08 +00002996
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00002997 f = openfile->current->next;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00002998 c = openfile->current->data[openfile->current_x];
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00002999
3000 openfile->current->next = NULL;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003001 openfile->current->data[openfile->current_x] = '\0';
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003002
3003 i = get_totsize(openfile->fileage, openfile->current);
3004
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003005 openfile->current->data[openfile->current_x] = c;
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003006 openfile->current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003007
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003008 if (constant && disable_cursorpos) {
3009 disable_cursorpos = FALSE;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003010 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003011 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003012
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003013 /* Display the current cursor position on the statusbar, and set
3014 * disable_cursorpos to FALSE. */
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003015 linepct = 100 * openfile->current->lineno /
3016 openfile->filebot->lineno;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003017 colpct = 100 * cur_xpt / cur_lenpt;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003018 charpct = (openfile->totsize == 0) ? 0 : 100 * i /
3019 openfile->totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003020
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003021 statusbar(
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003022 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003023 (long)openfile->current->lineno,
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003024 (long)openfile->filebot->lineno, linepct,
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003025 (unsigned long)cur_xpt, (unsigned long)cur_lenpt, colpct,
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003026 (unsigned long)i, (unsigned long)openfile->totsize, charpct);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003027
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003028 disable_cursorpos = FALSE;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003029}
3030
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003031/* Unconditionally display the current cursor position. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003032void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003033{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003034 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003035}
3036
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003037/* Highlight the current word being replaced or spell checked. We
3038 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003039void do_replace_highlight(bool highlight, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003040{
David Lawrence Ramsey6168cb72005-06-30 03:53:28 +00003041 size_t y = xplustabs(), word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003042
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003043 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003044 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003045 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003046
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003047 assert(y > 0);
3048
3049 if (word_len > y)
3050 y--;
3051
Chris Allegrettafb62f732000-12-05 11:36:41 +00003052 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003053
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003054 if (highlight)
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00003055 wattron(edit, reverse_attr);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003056
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003057#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003058 /* This is so we can show zero-length regexes. */
3059 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00003060 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003061 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003062#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003063 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003064
3065 if (word_len > y)
3066 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003067
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003068 if (highlight)
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00003069 wattroff(edit, reverse_attr);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003070}
3071
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003072#ifdef NANO_EXTRA
David Lawrence Ramsey315eb322005-11-28 19:35:29 +00003073#define CREDIT_LEN 55
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003074#define XLCREDIT_LEN 8
3075
David Lawrence Ramsey8ad58bc2005-08-16 03:02:46 +00003076/* Easter egg: Display credits. Assume nodelay(edit) and scrollok(edit)
3077 * are FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003078void do_credits(void)
3079{
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003080 bool old_more_space = ISSET(MORE_SPACE);
3081 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003082 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003083 const char *credits[CREDIT_LEN] = {
3084 NULL, /* "The nano text editor" */
3085 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003086 VERSION,
3087 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003088 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003089 "Chris Allegretta",
3090 "Jordi Mallach",
3091 "Adam Rogoyski",
3092 "Rob Siemborski",
3093 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003094 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003095 "David Benbennick",
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003096 "Mike Frysinger",
Chris Allegretta598106e2002-01-19 01:59:37 +00003097 "Ken Tyler",
3098 "Sven Guckes",
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003099 NULL, /* credits[15], handled below. */
Chris Allegretta598106e2002-01-19 01:59:37 +00003100 "Pauli Virtanen",
3101 "Daniele Medri",
3102 "Clement Laforet",
3103 "Tedi Heriyanto",
3104 "Bill Soudan",
3105 "Christian Weisgerber",
3106 "Erik Andersen",
3107 "Big Gaute",
3108 "Joshua Jensen",
3109 "Ryan Krebs",
3110 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003111 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003112 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003113 "Plattsburgh State University",
3114 "Benet Laboratories",
3115 "Amy Allegretta",
3116 "Linda Young",
3117 "Jeremy Robichaud",
3118 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003119 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003120 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003121 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003122 "Thomas Dickey",
3123 "Pavel Curtis",
3124 "Zeyd Ben-Halim",
3125 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003126 NULL, /* "and anyone else we forgot..." */
3127 NULL, /* "Thank you for using nano!" */
3128 "",
3129 "",
3130 "",
3131 "",
David Lawrence Ramsey315eb322005-11-28 19:35:29 +00003132 "(c) 1999-2004 Chris Allegretta",
3133 "(c) 2005 David Lawrence Ramsey",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003134 "",
3135 "",
3136 "",
3137 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003138 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003139 };
3140
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003141 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003142 N_("The nano text editor"),
3143 N_("version"),
3144 N_("Brought to you by:"),
3145 N_("Special thanks to:"),
3146 N_("The Free Software Foundation"),
3147 N_("For ncurses:"),
3148 N_("and anyone else we forgot..."),
3149 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003150 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003151
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003152 /* credits[15]: Make sure this name is displayed properly, since we
David Lawrence Ramsey62d616b2005-07-06 19:20:32 +00003153 * can't dynamically assign it above, using Unicode 00F6 (Latin
3154 * Small Letter O with Diaresis) if applicable. */
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003155 credits[15] =
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00003156#ifdef ENABLE_UTF8
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00003157 using_utf8() ? "Florian K\xC3\xB6nig" :
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003158#endif
3159 "Florian K\xF6nig";
3160
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003161 if (!old_more_space || !old_no_help) {
3162 SET(MORE_SPACE);
3163 SET(NO_HELP);
3164 window_init();
3165 }
3166
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003167 curs_set(0);
3168 nodelay(edit, TRUE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003169
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003170 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003171 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003172 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003173 blank_statusbar();
3174 blank_bottombars();
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003175
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003176 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003177 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003178 wrefresh(bottomwin);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003179 napms(700);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003180
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003181 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003182 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003183 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003184
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003185 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003186 const char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003187 size_t start_x;
3188
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003189 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003190 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003191
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003192 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003193 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003194 } else
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003195 what = credits[crpos];
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003196
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003197 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003198 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
3199 start_x, what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003200 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003201
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003202 wrefresh(edit);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003203
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003204 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003205 break;
3206 napms(700);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003207
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003208 scrollok(edit, TRUE);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003209 wscrl(edit, 1);
3210 scrollok(edit, FALSE);
3211 wrefresh(edit);
3212
3213 if ((kbinput = wgetch(edit)) != ERR)
3214 break;
3215 napms(700);
3216
3217 scrollok(edit, TRUE);
3218 wscrl(edit, 1);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003219 scrollok(edit, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003220 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003221 }
3222
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003223 if (kbinput != ERR)
3224 ungetch(kbinput);
3225
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003226 if (!old_more_space || !old_no_help) {
3227 UNSET(MORE_SPACE);
3228 UNSET(NO_HELP);
3229 window_init();
3230 }
3231
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003232 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003233 nodelay(edit, FALSE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003234
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003235 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003236}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003237#endif