blob: d2544bcfb31d724cc8851ebed12edf9f3ffd9045 [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * winio.c *
4 * *
Chris Allegretta8a07a962009-12-02 03:36:22 +00005 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, *
6 * 2008, 2009 Free Software Foundation, Inc. *
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 *
David Lawrence Ramseyd0035b42007-08-11 05:17:36 +00009 * the Free Software Foundation; either version 3, 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 Ramsey6335fb52007-01-01 05:15:32 +000033 /* The keystroke buffer, containing all the keystrokes we
34 * haven't handled yet at a given point. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +000035static size_t key_buffer_len = 0;
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +000036 /* The length of the keystroke buffer. */
David Lawrence Ramseyfe7d53e2005-06-25 20:56:36 +000037static int statusblank = 0;
David Lawrence Ramseyc1c818e2006-05-14 18:22:01 +000038 /* The number of keystrokes left after we call statusbar(),
39 * before we actually blank the statusbar. */
David Lawrence Ramseyea014742005-06-17 18:27:00 +000040static bool disable_cursorpos = FALSE;
David Lawrence Ramseyc1c818e2006-05-14 18:22:01 +000041 /* Should we temporarily disable constant cursor position
42 * display? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000043
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000044/* Control character compatibility:
45 *
46 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
47 * VT100, and VT220.
48 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
49 * VT220, and VT320.
50 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
51 * VT220, and VT320.
52 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
53 * VT220, and VT320.
54 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
55 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000056 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000057 * ANSI, VT100, and VT220, and which is Backspace under VT320.
58 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000059 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000060 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
61 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000062 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000063 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000064 * on which the VT320 sequences are translated by the keypad to KEY_DC
65 * and [nothing]. We work around this conflict via the REBIND_DELETE
66 * flag: if it's not set, we assume VT320 compatibility, and if it is,
67 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
68 * Hemel for helping work this conflict out.
69 *
70 * Escape sequence compatibility:
71 *
72 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +000073 * console, the FreeBSD console, the Mach console, xterm, rxvt, Eterm,
74 * and Terminal. Among these, there are several conflicts and
75 * omissions, outlined as follows:
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000076 *
77 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
78 * (Ctrl-I is also Tab on ANSI, which we already support.)
79 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
80 * NumLock off on Linux console; the latter is omitted. (The editing
81 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000082 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000083 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
84 * latter is omitted. (Mouse input will only work properly if the
85 * extended keypad value KEY_MOUSE is generated on mouse events
86 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000087 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000088 * omitted. (The editing keypad is more important to have working
89 * than the function keys, because the functions of the former are not
90 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000091 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000092 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000093 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000094 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +000095 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
96 * omitted. (The arrow keys, with or without modifiers, are more
97 * important to have working than the function keys, because the
98 * functions of the former are not arbitrary and the functions of the
99 * latter are.)
100 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
David Lawrence Ramsey25780252006-07-31 23:29:22 +0000101 * omitted. (Same as above.) */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000102
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000103/* Read in a sequence of keystrokes from win and save them in the
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000104 * keystroke buffer. This should only be called when the keystroke
105 * buffer is empty. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000106void get_key_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000107{
David Lawrence Ramseyec8a0552006-03-19 19:26:52 +0000108 int input;
109 size_t errcount;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000110
111 /* If the keystroke buffer isn't empty, get out. */
112 if (key_buffer != NULL)
113 return;
114
115 /* Read in the first character using blocking input. */
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000116#ifndef NANO_TINY
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000117 allow_pending_sigwinch(TRUE);
118#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000119
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +0000120 /* Just before reading in the first character, display any pending
121 * screen updates. */
122 doupdate();
123
David Lawrence Ramsey91493252006-03-19 19:25:29 +0000124 errcount = 0;
Chris Allegretta0dc26dc2009-01-24 22:40:41 +0000125 if (nodelay_mode) {
126 if ((input = wgetch(win)) == ERR)
127 return;
128 } else
129 while ((input = wgetch(win)) == ERR) {
130 errcount++;
David Lawrence Ramsey91493252006-03-19 19:25:29 +0000131
Chris Allegretta0dc26dc2009-01-24 22:40:41 +0000132 /* If we've failed to get a character MAX_BUF_SIZE times in a
133 * row, assume that the input source we were using is gone and
134 * die gracefully. We could check if errno is set to EIO
135 * ("Input/output error") and die gracefully in that case, but
136 * it's not always set properly. Argh. */
137 if (errcount == MAX_BUF_SIZE)
138 handle_hupterm(0);
139 }
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000140
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000141#ifndef NANO_TINY
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000142 allow_pending_sigwinch(FALSE);
143#endif
144
David Lawrence Ramsey14aa37c2007-05-25 16:54:06 +0000145 /* Increment the length of the keystroke buffer, and save the value
146 * of the keystroke at the end of it. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000147 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000148 key_buffer = (int *)nmalloc(sizeof(int));
149 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000150
151 /* Read in the remaining characters using non-blocking input. */
152 nodelay(win, TRUE);
153
154 while (TRUE) {
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000155#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000156 allow_pending_sigwinch(TRUE);
157#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000158
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000159 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000160
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000161 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000162 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000163 break;
164
David Lawrence Ramsey14aa37c2007-05-25 16:54:06 +0000165 /* Otherwise, increment the length of the keystroke buffer, and
166 * save the value of the keystroke at the end of it. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000167 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000168 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
169 sizeof(int));
170 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000171
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000172#ifndef NANO_TINY
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000173 allow_pending_sigwinch(FALSE);
174#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000175 }
176
177 /* Switch back to non-blocking input. */
178 nodelay(win, FALSE);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000179
180#ifdef DEBUG
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000181 fprintf(stderr, "get_key_buffer(): key_buffer_len = %lu\n", (unsigned long)key_buffer_len);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000182#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000183}
184
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000185/* Return the length of the keystroke buffer. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000186size_t get_key_buffer_len(void)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000187{
188 return key_buffer_len;
189}
190
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000191/* Add the keystrokes in input to the keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000192void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000193{
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000194#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000195 allow_pending_sigwinch(TRUE);
196 allow_pending_sigwinch(FALSE);
197#endif
198
199 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000200 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000201 return;
202
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000203 /* If adding input would put the keystroke buffer beyond maximum
204 * capacity, only add enough of input to put it at maximum
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000205 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000206 if (key_buffer_len + input_len < key_buffer_len)
207 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000208
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000209 /* Add the length of input to the length of the keystroke buffer,
210 * and reallocate the keystroke buffer so that it has enough room
211 * for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000212 key_buffer_len += input_len;
213 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
214 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000215
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000216 /* If the keystroke buffer wasn't empty before, move its beginning
217 * forward far enough so that we can add input to its beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000218 if (key_buffer_len > input_len)
219 memmove(key_buffer + input_len, key_buffer,
220 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000221
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000222 /* Copy input to the beginning of the keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000223 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000224}
225
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000226/* Put back the character stored in kbinput, putting it in byte range
227 * beforehand. If meta_key is TRUE, put back the Escape character after
228 * putting back kbinput. If func_key is TRUE, put back the function key
229 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000230void unget_kbinput(int kbinput, bool meta_key, bool func_key)
231{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000232 if (!func_key)
233 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000234
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000235 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000236
237 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000238 kbinput = NANO_CONTROL_3;
239 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000240 }
241}
242
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000243/* Try to read input_len characters from the keystroke buffer. If the
244 * keystroke buffer is empty and win isn't NULL, try to read in more
245 * characters from win and add them to the keystroke buffer before doing
246 * anything else. If the keystroke buffer is empty and win is NULL,
247 * return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000248int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000249{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000250 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000251
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000252#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000253 allow_pending_sigwinch(TRUE);
254 allow_pending_sigwinch(FALSE);
255#endif
256
257 if (key_buffer_len == 0) {
David Lawrence Ramsey7d15d1d2006-08-30 13:52:33 +0000258 if (win != NULL) {
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000259 get_key_buffer(win);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000260
David Lawrence Ramsey7d15d1d2006-08-30 13:52:33 +0000261 if (key_buffer_len == 0)
262 return NULL;
263 } else
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000264 return NULL;
265 }
266
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000267 /* If input_len is greater than the length of the keystroke buffer,
268 * only read the number of characters in the keystroke buffer. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000269 if (input_len > key_buffer_len)
270 input_len = key_buffer_len;
271
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000272 /* Subtract input_len from the length of the keystroke buffer, and
273 * allocate input so that it has enough room for input_len
274 * keystrokes. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000275 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000276 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000277
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000278 /* Copy input_len keystrokes from the beginning of the keystroke
279 * buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000280 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000281
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000282 /* If the keystroke buffer is empty, mark it as such. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000283 if (key_buffer_len == 0) {
284 free(key_buffer);
285 key_buffer = NULL;
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000286 /* If the keystroke buffer isn't empty, move its beginning forward
287 * far enough so that the keystrokes in input are no longer at its
288 * beginning. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000289 } else {
290 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000291 sizeof(int));
292 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
293 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000294 }
295
296 return input;
297}
298
299/* Read in a single character. If it's ignored, swallow it and go on.
300 * Otherwise, try to translate it from ASCII, meta key sequences, escape
301 * sequences, and/or extended keypad values. Set meta_key to TRUE when
302 * we get a meta key sequence, and set func_key to TRUE when we get an
303 * extended keypad value. Supported extended keypad values consist of
304 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
305 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
306 * the function keypad (F1-F16), and the numeric keypad with NumLock
307 * off. Assume nodelay(win) is FALSE. */
308int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
309{
310 int kbinput;
311
312 /* Read in a character and interpret it. Continue doing this until
313 * we get a recognized value or sequence. */
David Lawrence Ramseyfc0f8f82006-05-10 13:41:53 +0000314 while ((kbinput = parse_kbinput(win, meta_key, func_key)) == ERR);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000315
David Lawrence Ramsey6b49e9e2006-05-22 01:29:30 +0000316 /* If we read from the edit window, blank the statusbar if we need
317 * to. */
318 if (win == edit)
David Lawrence Ramseyce862362006-05-21 21:23:21 +0000319 check_statusblank();
320
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000321 return kbinput;
322}
323
324/* Translate ASCII characters, extended keypad values, and escape
325 * sequences into their corresponding key values. Set meta_key to TRUE
326 * when we get a meta key sequence, and set func_key to TRUE when we get
327 * a function key. Assume nodelay(win) is FALSE. */
David Lawrence Ramseyfc0f8f82006-05-10 13:41:53 +0000328int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000329{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000330 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000331 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000332
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000333 *meta_key = FALSE;
334 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000335
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000336 /* Read in a character. */
Chris Allegretta0dc26dc2009-01-24 22:40:41 +0000337 if (nodelay_mode) {
338 kbinput = get_input(win, 1);
339 if (kbinput == 0)
340 return 0;
341 } else
342 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000343
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000344 switch (*kbinput) {
345 case ERR:
346 break;
347 case NANO_CONTROL_3:
348 /* Increment the escape counter. */
349 escapes++;
350 switch (escapes) {
351 case 1:
352 /* One escape: wait for more input. */
353 case 2:
354 /* Two escapes: wait for more input. */
David Lawrence Ramseyf28ff9d2006-07-24 18:53:54 +0000355 case 3:
356 /* Three escapes: wait for more input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000357 break;
358 default:
David Lawrence Ramseyf28ff9d2006-07-24 18:53:54 +0000359 /* More than three escapes: limit the escape counter
360 * to no more than two, and wait for more input. */
361 escapes %= 3;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000362 }
363 break;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000364 default:
365 switch (escapes) {
366 case 0:
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000367 /* One non-escape: normal input mode. Save the
368 * non-escape character as the result. */
369 retval = *kbinput;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000370 break;
371 case 1:
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000372 /* Reset the escape counter. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000373 escapes = 0;
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000374 if (get_key_buffer_len() == 0) {
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000375 /* One escape followed by a non-escape, and
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000376 * there aren't any other keystrokes waiting:
377 * meta key sequence mode. Set meta_key to
378 * TRUE, and save the lowercase version of the
379 * non-escape character as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000380 *meta_key = TRUE;
381 retval = tolower(*kbinput);
David Lawrence Ramsey722b7282006-07-24 21:22:49 +0000382 } else
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000383 /* One escape followed by a non-escape, and
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000384 * there are other keystrokes waiting: escape
385 * sequence mode. Interpret the escape
386 * sequence. */
David Lawrence Ramsey5370b0c2006-07-23 17:54:35 +0000387 retval = parse_escape_seq_kbinput(win,
388 *kbinput);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000389 break;
390 case 2:
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000391 if (get_key_buffer_len() == 0) {
392 if (('0' <= *kbinput && *kbinput <= '2' &&
393 byte_digits == 0) || ('0' <= *kbinput &&
394 *kbinput <= '9' && byte_digits > 0)) {
395 /* Two escapes followed by one or more
396 * decimal digits, and there aren't any
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000397 * other keystrokes waiting: byte sequence
398 * mode. If the byte sequence's range is
399 * limited to 2XX (the first digit is in the
400 * '0' to '2' range and it's the first
401 * digit, or it's in the '0' to '9' range
402 * and it's not the first digit), increment
403 * the byte sequence counter and interpret
404 * the digit. If the byte sequence's range
405 * is not limited to 2XX, fall through. */
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000406 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000407
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000408 byte_digits++;
409 byte = get_byte_kbinput(*kbinput);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000410
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000411 if (byte != ERR) {
412 char *byte_mb;
413 int byte_mb_len, *seq, i;
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000414
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000415 /* If we've read in a complete byte
416 * sequence, reset the escape counter
417 * and the byte sequence counter, and
418 * put back the corresponding byte
419 * value. */
420 escapes = 0;
421 byte_digits = 0;
422
423 /* Put back the multibyte equivalent of
424 * the byte value. */
425 byte_mb = make_mbchar((long)byte,
426 &byte_mb_len);
427
428 seq = (int *)nmalloc(byte_mb_len *
429 sizeof(int));
430
431 for (i = 0; i < byte_mb_len; i++)
432 seq[i] = (unsigned char)byte_mb[i];
433
434 unget_input(seq, byte_mb_len);
435
436 free(byte_mb);
437 free(seq);
438 }
439 } else {
440 /* Reset the escape counter. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000441 escapes = 0;
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000442 if (byte_digits == 0)
443 /* Two escapes followed by a non-decimal
444 * digit or a decimal digit that would
445 * create a byte sequence greater than
446 * 2XX, we're not in the middle of a
447 * byte sequence, and there aren't any
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000448 * other keystrokes waiting: control
449 * character sequence mode. Interpret
450 * the control sequence and save the
451 * corresponding control character as
452 * the result. */
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000453 retval = get_control_kbinput(*kbinput);
454 else {
455 /* If we're in the middle of a byte
456 * sequence, reset the byte sequence
457 * counter and save the character we got
458 * as the result. */
459 byte_digits = 0;
460 retval = *kbinput;
461 }
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000462 }
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000463 } else {
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000464 /* Two escapes followed by a non-escape, and
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000465 * there are other keystrokes waiting: combined
466 * meta and escape sequence mode. Reset the
467 * escape counter, set meta_key to TRUE, and
468 * interpret the escape sequence. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000469 escapes = 0;
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000470 *meta_key = TRUE;
David Lawrence Ramsey5370b0c2006-07-23 17:54:35 +0000471 retval = parse_escape_seq_kbinput(win,
472 *kbinput);
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000473 }
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000474 break;
David Lawrence Ramseyf28ff9d2006-07-24 18:53:54 +0000475 case 3:
476 /* Reset the escape counter. */
477 escapes = 0;
478 if (get_key_buffer_len() == 0)
479 /* Three escapes followed by a non-escape, and
480 * there aren't any other keystrokes waiting:
481 * normal input mode. Save the non-escape
482 * character as the result. */
483 retval = *kbinput;
484 else
485 /* Three escapes followed by a non-escape, and
486 * there are other keystrokes waiting: combined
487 * control character and escape sequence mode.
488 * Interpret the escape sequence, and interpret
489 * the result as a control sequence. */
490 retval = get_control_kbinput(
491 parse_escape_seq_kbinput(win,
492 *kbinput));
David Lawrence Ramsey916c7c22006-12-02 17:17:09 +0000493 break;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000494 }
495 }
496
David Lawrence Ramsey5f274c42006-04-28 19:27:41 +0000497 if (retval != ERR) {
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000498 switch (retval) {
499 case NANO_CONTROL_8:
Chris Allegretta637daa82011-02-07 14:45:56 +0000500 retval = ISSET(REBIND_DELETE) ? sc_seq_or(do_delete, 0) :
501 sc_seq_or(do_backspace, 0);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000502 break;
503 case KEY_DOWN:
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000504#ifdef KEY_SDOWN
505 /* ncurses and Slang don't support KEY_SDOWN. */
506 case KEY_SDOWN:
507#endif
Chris Allegretta637daa82011-02-07 14:45:56 +0000508 retval = sc_seq_or(do_down_void, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000509 break;
510 case KEY_UP:
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000511#ifdef KEY_SUP
512 /* ncurses and Slang don't support KEY_SUP. */
513 case KEY_SUP:
514#endif
Chris Allegretta637daa82011-02-07 14:45:56 +0000515 retval = sc_seq_or(do_up_void, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000516 break;
517 case KEY_LEFT:
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000518#ifdef KEY_SLEFT
519 /* Slang doesn't support KEY_SLEFT. */
520 case KEY_SLEFT:
521#endif
Chris Allegretta637daa82011-02-07 14:45:56 +0000522 retval = sc_seq_or(do_left, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000523 break;
524 case KEY_RIGHT:
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000525#ifdef KEY_SRIGHT
526 /* Slang doesn't support KEY_SRIGHT. */
527 case KEY_SRIGHT:
528#endif
Chris Allegretta637daa82011-02-07 14:45:56 +0000529 retval = sc_seq_or(do_right, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000530 break;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000531#ifdef KEY_SHOME
532 /* HP-UX 10-11 and Slang don't support KEY_SHOME. */
533 case KEY_SHOME:
534#endif
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000535 case KEY_A1: /* Home (7) on numeric keypad with
536 * NumLock off. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000537 retval = sc_seq_or(do_home, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000538 break;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000539 case KEY_BACKSPACE:
Chris Allegretta637daa82011-02-07 14:45:56 +0000540 retval = sc_seq_or(do_backspace, *kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000541 break;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000542#ifdef KEY_SDC
543 /* Slang doesn't support KEY_SDC. */
544 case KEY_SDC:
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000545 if (ISSET(REBIND_DELETE))
Chris Allegretta637daa82011-02-07 14:45:56 +0000546 retval = sc_seq_or(do_delete, *kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000547 else
Chris Allegretta637daa82011-02-07 14:45:56 +0000548 retval = sc_seq_or(do_backspace, *kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000549 break;
Chris Allegretta17436ce2008-03-11 03:03:53 +0000550#endif
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000551#ifdef KEY_SIC
552 /* Slang doesn't support KEY_SIC. */
553 case KEY_SIC:
Chris Allegretta637daa82011-02-07 14:45:56 +0000554 retval = sc_seq_or(do_insertfile_void, *kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000555 break;
Chris Allegretta17436ce2008-03-11 03:03:53 +0000556#endif
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000557 case KEY_C3: /* PageDown (4) on numeric keypad with
558 * NumLock off. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000559 retval = sc_seq_or(do_page_down, *kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000560 break;
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000561 case KEY_A3: /* PageUp (9) on numeric keypad with
562 * NumLock off. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000563 retval = sc_seq_or(do_page_up, *kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000564 break;
565 case KEY_ENTER:
Chris Allegretta637daa82011-02-07 14:45:56 +0000566 retval = sc_seq_or(do_enter_void, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000567 break;
568 case KEY_B2: /* Center (5) on numeric keypad with
569 * NumLock off. */
570 retval = ERR;
571 break;
572 case KEY_C1: /* End (1) on numeric keypad with
573 * NumLock off. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000574#ifdef KEY_SEND
575 /* HP-UX 10-11 and Slang don't support KEY_SEND. */
576 case KEY_SEND:
577#endif
Chris Allegretta637daa82011-02-07 14:45:56 +0000578 retval = sc_seq_or(do_end, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000579 break;
580#ifdef KEY_BEG
581 /* Slang doesn't support KEY_BEG. */
582 case KEY_BEG: /* Center (5) on numeric keypad with
583 * NumLock off. */
584 retval = ERR;
585 break;
586#endif
David Lawrence Ramsey6a8b3502007-04-18 14:06:34 +0000587#ifdef KEY_CANCEL
588 /* Slang doesn't support KEY_CANCEL. */
589 case KEY_CANCEL:
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000590#ifdef KEY_SCANCEL
591 /* Slang doesn't support KEY_SCANCEL. */
592 case KEY_SCANCEL:
David Lawrence Ramsey6a8b3502007-04-18 14:06:34 +0000593#endif
Chris Allegretta637daa82011-02-07 14:45:56 +0000594 retval = first_sc_for(currmenu, do_cancel)->seq;
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000595 break;
596#endif
597#ifdef KEY_SBEG
598 /* Slang doesn't support KEY_SBEG. */
599 case KEY_SBEG: /* Center (5) on numeric keypad with
600 * NumLock off. */
601 retval = ERR;
602 break;
603#endif
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000604#ifdef KEY_SSUSPEND
605 /* Slang doesn't support KEY_SSUSPEND. */
606 case KEY_SSUSPEND:
Chris Allegretta637daa82011-02-07 14:45:56 +0000607 retval = sc_seq_or(do_suspend_void, 0);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000608 break;
609#endif
610#ifdef KEY_SUSPEND
611 /* Slang doesn't support KEY_SUSPEND. */
612 case KEY_SUSPEND:
Chris Allegretta637daa82011-02-07 14:45:56 +0000613 retval = sc_seq_or(do_suspend_void, 0);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000614 break;
615#endif
616#ifdef PDCURSES
617 case KEY_SHIFT_L:
618 case KEY_SHIFT_R:
619 case KEY_CONTROL_L:
620 case KEY_CONTROL_R:
621 case KEY_ALT_L:
622 case KEY_ALT_R:
623 retval = ERR;
624 break;
625#endif
626#if !defined(NANO_TINY) && defined(KEY_RESIZE)
627 /* Since we don't change the default SIGWINCH handler when
628 * NANO_TINY is defined, KEY_RESIZE is never generated.
629 * Also, Slang and SunOS 5.7-5.9 don't support
630 * KEY_RESIZE. */
631 case KEY_RESIZE:
632 retval = ERR;
633 break;
634#endif
635 }
David Lawrence Ramsey5f274c42006-04-28 19:27:41 +0000636
David Lawrence Ramseyb159f942006-07-28 17:06:27 +0000637 /* If our result is an extended keypad value (i.e. a value
David Lawrence Ramsey5f274c42006-04-28 19:27:41 +0000638 * outside of byte range), set func_key to TRUE. */
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000639 if (retval != ERR)
640 *func_key = !is_byte(retval);
David Lawrence Ramsey5f274c42006-04-28 19:27:41 +0000641 }
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000642
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000643#ifdef DEBUG
David Lawrence Ramsey23994bd2006-07-19 13:34:55 +0000644 fprintf(stderr, "parse_kbinput(): kbinput = %d, meta_key = %s, func_key = %s, escapes = %d, byte_digits = %d, retval = %d\n", *kbinput, *meta_key ? "TRUE" : "FALSE", *func_key ? "TRUE" : "FALSE", escapes, byte_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000645#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000646
David Lawrence Ramseyad36bdc2006-12-02 17:22:21 +0000647 free(kbinput);
648
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000649 /* Return the result. */
650 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000651}
652
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000653/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000654 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +0000655 * are generated when the keypad doesn't support the needed keys.
656 * Assume that Escape has already been read in. */
657int get_escape_seq_kbinput(const int *seq, size_t seq_len)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000658{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000659 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000660
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000661 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000662 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000663 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000664 switch (seq[1]) {
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000665 case '1':
666 if (seq_len >= 3) {
667 switch (seq[2]) {
668 case ';':
669 if (seq_len >= 4) {
670 switch (seq[3]) {
671 case '2':
672 if (seq_len >= 5) {
673 switch (seq[4]) {
674 case 'A': /* Esc O 1 ; 2 A == Shift-Up on
675 * Terminal. */
676 case 'B': /* Esc O 1 ; 2 B == Shift-Down on
677 * Terminal. */
678 case 'C': /* Esc O 1 ; 2 C == Shift-Right on
679 * Terminal. */
680 case 'D': /* Esc O 1 ; 2 D == Shift-Left on
681 * Terminal. */
682 retval = get_escape_seq_abcd(seq[4]);
683 break;
684 case 'P': /* Esc O 1 ; 2 P == F13 on
685 * Terminal. */
686 retval = KEY_F(13);
687 break;
688 case 'Q': /* Esc O 1 ; 2 Q == F14 on
689 * Terminal. */
690 retval = KEY_F(14);
691 break;
692 case 'R': /* Esc O 1 ; 2 R == F15 on
693 * Terminal. */
694 retval = KEY_F(15);
695 break;
696 case 'S': /* Esc O 1 ; 2 S == F16 on
697 * Terminal. */
698 retval = KEY_F(16);
699 break;
700 }
701 }
702 break;
703 case '5':
704 if (seq_len >= 5) {
705 switch (seq[4]) {
706 case 'A': /* Esc O 1 ; 5 A == Ctrl-Up on
707 * Terminal. */
708 case 'B': /* Esc O 1 ; 5 B == Ctrl-Down on
709 * Terminal. */
710 case 'C': /* Esc O 1 ; 5 C == Ctrl-Right on
711 * Terminal. */
712 case 'D': /* Esc O 1 ; 5 D == Ctrl-Left on
713 * Terminal. */
714 retval = get_escape_seq_abcd(seq[4]);
715 break;
716 }
717 }
718 break;
719 }
720 }
721 break;
722 }
723 }
724 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000725 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000726 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000727 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000728 case 'P': /* Esc O 2 P == F13 on
729 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000730 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000731 break;
732 case 'Q': /* Esc O 2 Q == F14 on
733 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000734 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000735 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000736 case 'R': /* Esc O 2 R == F15 on
737 * xterm. */
738 retval = KEY_F(15);
739 break;
740 case 'S': /* Esc O 2 S == F16 on
741 * xterm. */
742 retval = KEY_F(16);
743 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000744 }
745 }
746 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000747 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
748 case 'B': /* Esc O B == Down on
749 * VT100/VT320/xterm. */
750 case 'C': /* Esc O C == Right on
751 * VT100/VT320/xterm. */
752 case 'D': /* Esc O D == Left on
753 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000754 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000755 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000756 case 'E': /* Esc O E == Center (5) on numeric keypad
757 * with NumLock off on xterm. */
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +0000758 retval = KEY_B2;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000759 break;
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000760 case 'F': /* Esc O F == End on xterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000761 retval = sc_seq_or(do_end, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000762 break;
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000763 case 'H': /* Esc O H == Home on xterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000764 retval = sc_seq_or(do_home, 0);;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000765 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000766 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000767 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000768 * rxvt/Eterm. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000769 retval = sc_seq_or(do_home, 0);;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000770 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000771 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000772 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000773 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000774 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000775 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000776 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000777 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000778 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000779 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000780 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000781 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000782 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000783 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000784 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000785 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000786 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000787 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000788 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000789 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000790 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000791 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000792 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000793 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000794 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000795 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000796 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000797 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000798 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000799 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000800 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000801 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000802 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000803 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000804 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000805 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000806 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000807 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000808 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000809 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000810 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000811 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000812 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000813 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000814 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000815 break;
816 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000817 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000818 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000819 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000820 break;
821 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000822 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000823 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey8f36d092005-09-24 19:42:48 +0000824 retval = ',';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000825 break;
826 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000827 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000828 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000829 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000830 break;
831 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000832 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000833 * xterm/rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000834 retval = sc_seq_or(do_delete, 0);;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000835 break;
836 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000837 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000838 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000839 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000840 break;
841 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000842 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000843 * rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000844 retval = sc_seq_or(do_insertfile_void, 0);;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000845 break;
846 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000847 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000848 * rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000849 retval = sc_seq_or(do_end, 0);;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000850 break;
851 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000852 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000853 * rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000854 retval = sc_seq_or(do_down_void, 0);;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000855 break;
856 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000857 * keypad with NumLock off on VT100/VT220/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000858 * VT320/rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000859 retval = sc_seq_or(do_page_down, 0);;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000860 break;
861 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000862 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000863 * rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000864 retval = sc_seq_or(do_left, 0);;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000865 break;
866 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000867 * with NumLock off on VT100/VT220/VT320/
868 * rxvt/Eterm. */
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +0000869 retval = KEY_B2;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000870 break;
871 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000872 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000873 * rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000874 retval = sc_seq_or(do_right, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000875 break;
876 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000877 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000878 * rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000879 retval = sc_seq_or(do_home, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000880 break;
881 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000882 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000883 * rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000884 retval = sc_seq_or(do_up_void, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000885 break;
886 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000887 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000888 * rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000889 retval = sc_seq_or(do_page_up, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000890 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000891 }
892 break;
893 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000894 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000895 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000896 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000897 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000898 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000899 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000900 break;
901 }
902 break;
903 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000904 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000905 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000906 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000907 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000908 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
909 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000910 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000911 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000912 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
913 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000914 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000915 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000916 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
917 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000918 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000919 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000920 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
921 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000922 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000923 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000924 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
925 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000926 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000927 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000928 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000929 * VT220/VT320/Linux console/
930 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000931 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000932 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000933 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000934 * VT220/VT320/Linux console/
935 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000936 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000937 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000938 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000939 * VT220/VT320/Linux console/
940 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000941 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000942 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000943 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000944 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000945 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000946 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000947 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000948 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000949 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
950 * xterm. */
951 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
952 * xterm. */
953 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
954 * xterm. */
955 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
956 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000957 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000958 break;
959 }
960 }
961 break;
962 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000963 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000964 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000965 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
966 * xterm. */
967 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
968 * xterm. */
969 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
970 * xterm. */
971 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
972 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000973 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000974 break;
975 }
976 }
977 break;
978 }
979 }
980 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000981 default: /* Esc [ 1 ~ == Home on
982 * VT320/Linux console. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000983 retval = sc_seq_or(do_home, 0);;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000984 break;
985 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000986 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000987 break;
988 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000989 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000990 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000991 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000992 * VT220/VT320/Linux console/
993 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000994 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000995 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000996 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000997 * VT220/VT320/Linux console/
998 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000999 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001000 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001001 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001002 * VT220/VT320/Linux console/
1003 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001004 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001005 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001006 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001007 * VT220/VT320/Linux console/
1008 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001009 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001010 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001011 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001012 * VT220/VT320/Linux console/
1013 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001014 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001015 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001016 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001017 * VT220/VT320/Linux console/
1018 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001019 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001020 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +00001021 case '8': /* Esc [ 2 8 ~ == F15 on
1022 * VT220/VT320/Linux console/
1023 * rxvt/Eterm. */
1024 retval = KEY_F(15);
1025 break;
1026 case '9': /* Esc [ 2 9 ~ == F16 on
1027 * VT220/VT320/Linux console/
1028 * rxvt/Eterm. */
1029 retval = KEY_F(16);
1030 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001031 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001032 * VT220/VT320/Linux console/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +00001033 * xterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001034 retval = sc_seq_or(do_insertfile_void, 0);;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001035 break;
1036 }
1037 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001038 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001039 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +00001040 * Linux console/xterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001041 retval = sc_seq_or(do_delete, 0);;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001042 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001043 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001044 * console/xterm. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001045 retval = sc_seq_or(do_end, 0);;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001046 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001047 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +00001048 * Linux console/xterm/Terminal;
1049 * Esc [ 5 ^ == PageUp on Eterm. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001050 retval = sc_seq_or(do_page_up, 0);;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001051 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001052 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +00001053 * Linux console/xterm/Terminal;
1054 * Esc [ 6 ^ == PageDown on Eterm. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001055 retval = sc_seq_or(do_page_down, 0);;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001056 break;
1057 case '7': /* Esc [ 7 ~ == Home on rxvt. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001058 retval = sc_seq_or(do_home, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001059 break;
1060 case '8': /* Esc [ 8 ~ == End on rxvt. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001061 retval = sc_seq_or(do_end, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001062 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001063 case '9': /* Esc [ 9 == Delete on Mach console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001064 retval = sc_seq_or(do_delete, 0);;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001065 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001066 case '@': /* Esc [ @ == Insert on Mach console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001067 retval = sc_seq_or(do_insertfile_void, 0);;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001068 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001069 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001070 * console/FreeBSD console/Mach console/
David Lawrence Ramseya31d54e2007-04-18 13:48:37 +00001071 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001072 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001073 * console/FreeBSD console/Mach console/
David Lawrence Ramseya31d54e2007-04-18 13:48:37 +00001074 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001075 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001076 * console/FreeBSD console/Mach console/
David Lawrence Ramseya31d54e2007-04-18 13:48:37 +00001077 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001078 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001079 * console/FreeBSD console/Mach console/
David Lawrence Ramseya31d54e2007-04-18 13:48:37 +00001080 * rxvt/Eterm/Terminal. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001081 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001082 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001083 case 'E': /* Esc [ E == Center (5) on numeric keypad
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +00001084 * with NumLock off on FreeBSD console/
1085 * Terminal. */
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +00001086 retval = KEY_B2;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001087 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001088 case 'F': /* Esc [ F == End on FreeBSD
1089 * console/Eterm. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001090 retval = sc_seq_or(do_end, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001091 break;
1092 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001093 * console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001094 retval = sc_seq_or(do_page_down, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001095 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001096 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001097 * console/Mach console/Eterm. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001098 retval = sc_seq_or(do_home, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001099 break;
1100 case 'I': /* Esc [ I == PageUp on FreeBSD
1101 * console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001102 retval = sc_seq_or(do_page_up, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001103 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001104 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001105 * console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001106 retval = sc_seq_or(do_insertfile_void, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001107 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001108 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001109 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001110 break;
1111 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001112 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001113 break;
1114 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001115 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001116 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001117 case 'P': /* Esc [ O P == F1 on
1118 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001119 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001120 break;
1121 case 'Q': /* Esc [ O Q == F2 on
1122 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001123 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001124 break;
1125 case 'R': /* Esc [ O R == F3 on
1126 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001127 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001128 break;
1129 case 'S': /* Esc [ O S == F4 on
1130 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001131 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001132 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001133 }
David Lawrence Ramseyec729752005-09-25 18:42:05 +00001134 } else
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001135 /* Esc [ O == F3 on FreeBSD console. */
1136 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001137 break;
1138 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001139 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001140 break;
1141 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001142 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001143 break;
1144 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001145 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001146 break;
1147 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001148 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001149 break;
1150 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001151 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001152 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001153 case 'U': /* Esc [ U == PageDown on Mach console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001154 retval = sc_seq_or(do_page_down, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001155 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001156 case 'V': /* Esc [ V == PageUp on Mach console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001157 retval = sc_seq_or(do_page_up, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001158 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001159 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001160 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001161 break;
1162 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001163 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001164 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001165 case 'Y': /* Esc [ Y == End on Mach console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001166 retval = sc_seq_or(do_end, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001167 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001168 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001169 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001170 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001171 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001172 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001173 case 'c': /* Esc [ c == Shift-Right on rxvt/
1174 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001175 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001176 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001177 break;
1178 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001179 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001180 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001181 case 'A': /* Esc [ [ A == F1 on Linux
1182 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001183 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001184 break;
1185 case 'B': /* Esc [ [ B == F2 on Linux
1186 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001187 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001188 break;
1189 case 'C': /* Esc [ [ C == F3 on Linux
1190 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001191 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001192 break;
1193 case 'D': /* Esc [ [ D == F4 on Linux
1194 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001195 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001196 break;
1197 case 'E': /* Esc [ [ E == F5 on Linux
1198 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001199 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001200 break;
1201 }
1202 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001203 break;
1204 }
1205 break;
1206 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001207 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001208
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001209#ifdef DEBUG
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +00001210 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d\n", retval);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001211#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001212
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001213 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001214}
1215
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001216/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001217 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001218 * to many escape sequences. */
1219int get_escape_seq_abcd(int kbinput)
1220{
1221 switch (tolower(kbinput)) {
1222 case 'a':
Chris Allegretta637daa82011-02-07 14:45:56 +00001223 return sc_seq_or(do_up_void, 0);;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001224 case 'b':
Chris Allegretta637daa82011-02-07 14:45:56 +00001225 return sc_seq_or(do_down_void, 0);;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001226 case 'c':
Chris Allegretta637daa82011-02-07 14:45:56 +00001227 return sc_seq_or(do_right, 0);;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001228 case 'd':
Chris Allegretta637daa82011-02-07 14:45:56 +00001229 return sc_seq_or(do_left, 0);;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001230 default:
1231 return ERR;
1232 }
1233}
1234
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001235/* Interpret the escape sequence in the keystroke buffer, the first
David Lawrence Ramsey5370b0c2006-07-23 17:54:35 +00001236 * character of which is kbinput. Assume that the keystroke buffer
1237 * isn't empty, and that the initial escape has already been read in. */
1238int parse_escape_seq_kbinput(WINDOW *win, int kbinput)
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001239{
1240 int retval, *seq;
1241 size_t seq_len;
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001242
1243 /* Put back the non-escape character, get the complete escape
1244 * sequence, translate the sequence into its corresponding key
1245 * value, and save that as the result. */
1246 unget_input(&kbinput, 1);
1247 seq_len = get_key_buffer_len();
1248 seq = get_input(NULL, seq_len);
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +00001249 retval = get_escape_seq_kbinput(seq, seq_len);
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001250
1251 free(seq);
1252
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +00001253 /* If we got an unrecognized escape sequence, throw it out. */
1254 if (retval == ERR) {
David Lawrence Ramsey8a723702006-07-23 18:00:50 +00001255 if (win == edit) {
David Lawrence Ramsey5370b0c2006-07-23 17:54:35 +00001256 statusbar(_("Unknown Command"));
1257 beep();
1258 }
1259 }
1260
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001261#ifdef DEBUG
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +00001262 fprintf(stderr, "parse_escape_seq_kbinput(): kbinput = %d, seq_len = %lu, retval = %d\n", kbinput, (unsigned long)seq_len, retval);
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001263#endif
1264
1265 return retval;
1266}
1267
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001268/* Translate a byte sequence: turn a three-digit decimal number (from
1269 * 000 to 255) into its corresponding byte value. */
David Lawrence Ramseyfc0f8f82006-05-10 13:41:53 +00001270int get_byte_kbinput(int kbinput)
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001271{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001272 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001273 int retval = ERR;
1274
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001275 /* Increment the byte digit counter. */
1276 byte_digits++;
1277
1278 switch (byte_digits) {
1279 case 1:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001280 /* First digit: This must be from zero to two. Put it in
1281 * the 100's position of the byte sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001282 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001283 byte = (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001284 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001285 /* This isn't the start of a byte sequence. Return this
1286 * character as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001287 retval = kbinput;
1288 break;
1289 case 2:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001290 /* Second digit: This must be from zero to five if the first
1291 * was two, and may be any decimal value if the first was
1292 * zero or one. Put it in the 10's position of the byte
1293 * sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001294 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1295 '6' <= kbinput && kbinput <= '9'))
1296 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001297 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001298 /* This isn't the second digit of a byte sequence.
1299 * Return this character as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001300 retval = kbinput;
1301 break;
1302 case 3:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001303 /* Third digit: This must be from zero to five if the first
1304 * was two and the second was between zero and five, and may
1305 * be any decimal value if the first was zero or one and the
1306 * second was between six and nine. Put it in the 1's
1307 * position of the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001308 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1309 '6' <= kbinput && kbinput <= '9')) {
David Lawrence Ramsey28889642006-05-30 20:51:15 +00001310 byte += kbinput - '0';
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001311 /* If this character is a valid decimal value, then the
1312 * byte sequence is complete. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001313 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001314 } else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001315 /* This isn't the third digit of a byte sequence.
1316 * Return this character as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001317 retval = kbinput;
1318 break;
1319 default:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001320 /* If there are more than three digits, return this
1321 * character as the result. (Maybe we should produce an
1322 * error instead?) */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001323 retval = kbinput;
1324 break;
1325 }
1326
1327 /* If we have a result, reset the byte digit counter and the byte
1328 * sequence holder. */
1329 if (retval != ERR) {
1330 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001331 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001332 }
1333
1334#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001335 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 +00001336#endif
1337
1338 return retval;
1339}
1340
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001341#ifdef ENABLE_UTF8
David Lawrence Ramsey7f1b1192006-05-28 17:30:28 +00001342/* If the character in kbinput is a valid hexadecimal digit, multiply it
1343 * by factor and add the result to uni. */
1344long add_unicode_digit(int kbinput, long factor, long *uni)
1345{
1346 long retval = ERR;
1347
1348 if ('0' <= kbinput && kbinput <= '9')
1349 *uni += (kbinput - '0') * factor;
1350 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
1351 *uni += (tolower(kbinput) - 'a' + 10) * factor;
1352 else
1353 /* If this character isn't a valid hexadecimal value, save it as
1354 * the result. */
1355 retval = kbinput;
1356
1357 return retval;
1358}
1359
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001360/* Translate a Unicode sequence: turn a six-digit hexadecimal number
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001361 * (from 000000 to 10FFFF, case-insensitive) into its corresponding
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001362 * multibyte value. */
David Lawrence Ramseyfc0f8f82006-05-10 13:41:53 +00001363long get_unicode_kbinput(int kbinput)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001364{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001365 static int uni_digits = 0;
1366 static long uni = 0;
1367 long retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001368
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001369 /* Increment the Unicode digit counter. */
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001370 uni_digits++;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001371
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001372 switch (uni_digits) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001373 case 1:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001374 /* First digit: This must be zero or one. Put it in the
1375 * 0x100000's position of the Unicode sequence holder. */
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001376 if ('0' <= kbinput && kbinput <= '1')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001377 uni = (kbinput - '0') * 0x100000;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001378 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001379 /* This isn't the first digit of a Unicode sequence.
1380 * Return this character as the result. */
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001381 retval = kbinput;
1382 break;
1383 case 2:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001384 /* Second digit: This must be zero if the first was one, and
1385 * may be any hexadecimal value if the first was zero. Put
1386 * it in the 0x10000's position of the Unicode sequence
1387 * holder. */
1388 if (uni == 0 || '0' == kbinput)
1389 retval = add_unicode_digit(kbinput, 0x10000, &uni);
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001390 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001391 /* This isn't the second digit of a Unicode sequence.
1392 * Return this character as the result. */
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001393 retval = kbinput;
1394 break;
1395 case 3:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001396 /* Third digit: This may be any hexadecimal value. Put it
1397 * in the 0x1000's position of the Unicode sequence
1398 * holder. */
1399 retval = add_unicode_digit(kbinput, 0x1000, &uni);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001400 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001401 case 4:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001402 /* Fourth digit: This may be any hexadecimal value. Put it
1403 * in the 0x100's position of the Unicode sequence
1404 * holder. */
1405 retval = add_unicode_digit(kbinput, 0x100, &uni);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001406 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001407 case 5:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001408 /* Fifth digit: This may be any hexadecimal value. Put it
1409 * in the 0x10's position of the Unicode sequence holder. */
1410 retval = add_unicode_digit(kbinput, 0x10, &uni);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001411 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001412 case 6:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001413 /* Sixth digit: This may be any hexadecimal value. Put it
1414 * in the 0x1's position of the Unicode sequence holder. */
1415 retval = add_unicode_digit(kbinput, 0x1, &uni);
1416 /* If this character is a valid hexadecimal value, then the
1417 * Unicode sequence is complete. */
1418 if (retval == ERR)
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001419 retval = uni;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001420 break;
1421 default:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001422 /* If there are more than six digits, return this character
1423 * as the result. (Maybe we should produce an error
1424 * instead?) */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001425 retval = kbinput;
1426 break;
1427 }
1428
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001429 /* If we have a result, reset the Unicode digit counter and the
1430 * Unicode sequence holder. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001431 if (retval != ERR) {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001432 uni_digits = 0;
1433 uni = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001434 }
1435
1436#ifdef DEBUG
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001437 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 +00001438#endif
1439
1440 return retval;
1441}
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001442#endif /* ENABLE_UTF8 */
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001443
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001444/* Translate a control character sequence: turn an ASCII non-control
1445 * character into its corresponding control character. */
1446int get_control_kbinput(int kbinput)
1447{
1448 int retval;
1449
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001450 /* Ctrl-Space (Ctrl-2, Ctrl-@, Ctrl-`) */
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001451 if (kbinput == ' ' || kbinput == '2')
1452 retval = NANO_CONTROL_SPACE;
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001453 /* Ctrl-/ (Ctrl-7, Ctrl-_) */
1454 else if (kbinput == '/')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001455 retval = NANO_CONTROL_7;
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001456 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-/, Ctrl-_) */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001457 else if ('3' <= kbinput && kbinput <= '7')
1458 retval = kbinput - 24;
1459 /* Ctrl-8 (Ctrl-?) */
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001460 else if (kbinput == '8' || kbinput == '?')
1461 retval = NANO_CONTROL_8;
David Lawrence Ramsey51cb7fd2006-05-20 17:19:09 +00001462 /* Ctrl-@ (Ctrl-Space, Ctrl-2, Ctrl-`) to Ctrl-_ (Ctrl-/, Ctrl-7) */
1463 else if ('@' <= kbinput && kbinput <= '_')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001464 retval = kbinput - '@';
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001465 /* Ctrl-` (Ctrl-2, Ctrl-Space, Ctrl-@) to Ctrl-~ (Ctrl-6, Ctrl-^) */
1466 else if ('`' <= kbinput && kbinput <= '~')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001467 retval = kbinput - '`';
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001468 else
1469 retval = kbinput;
1470
1471#ifdef DEBUG
1472 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1473#endif
1474
1475 return retval;
1476}
1477
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +00001478/* Put the output-formatted characters in output back into the keystroke
1479 * buffer, so that they can be parsed and displayed as output again. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001480void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001481{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001482 int *input;
1483 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001484
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001485 if (output_len == 0)
1486 return;
1487
1488 input = (int *)nmalloc(output_len * sizeof(int));
David Lawrence Ramseybd539802006-12-02 23:39:16 +00001489
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001490 for (i = 0; i < output_len; i++)
1491 input[i] = (int)output[i];
David Lawrence Ramseybd539802006-12-02 23:39:16 +00001492
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001493 unget_input(input, output_len);
David Lawrence Ramseybd539802006-12-02 23:39:16 +00001494
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001495 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001496}
1497
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001498/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001499 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1500int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1501{
1502 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001503
1504 /* Turn off flow control characters if necessary so that we can type
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001505 * them in verbatim, and turn the keypad off if necessary so that we
1506 * don't get extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001507 if (ISSET(PRESERVE))
1508 disable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001509 if (!ISSET(REBIND_KEYPAD))
1510 keypad(win, FALSE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001511
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001512 /* Read in a stream of characters and interpret it if possible. */
1513 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001514
1515 /* Turn flow control characters back on if necessary and turn the
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001516 * keypad back on if necessary now that we're done. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001517 if (ISSET(PRESERVE))
1518 enable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001519 if (!ISSET(REBIND_KEYPAD))
1520 keypad(win, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001521
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001522 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001523}
1524
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001525/* Read in a stream of all available characters, and return the length
1526 * of the string in kbinput_len. Translate the first few characters of
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001527 * the input into the corresponding multibyte value if possible. After
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00001528 * that, leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001529int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001530{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001531 int *kbinput, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001532
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001533 /* Read in the first keystroke. */
1534 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001535
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001536#ifdef ENABLE_UTF8
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001537 if (using_utf8()) {
1538 /* Check whether the first keystroke is a valid hexadecimal
1539 * digit. */
David Lawrence Ramseya5b1ca22006-05-28 17:09:49 +00001540 long uni = get_unicode_kbinput(*kbinput);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001541
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001542 /* If the first keystroke isn't a valid hexadecimal digit, put
1543 * back the first keystroke. */
1544 if (uni != ERR)
1545 unget_input(kbinput, 1);
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001546
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001547 /* Otherwise, read in keystrokes until we have a complete
1548 * Unicode sequence, and put back the corresponding Unicode
1549 * value. */
1550 else {
1551 char *uni_mb;
1552 int uni_mb_len, *seq, i;
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001553
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001554 if (win == edit)
1555 /* TRANSLATORS: This is displayed during the input of a
1556 * six-digit hexadecimal Unicode character code. */
1557 statusbar(_("Unicode Input"));
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001558
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001559 while (uni == ERR) {
1560 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001561
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001562 uni = get_unicode_kbinput(*kbinput);
1563 }
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001564
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001565 /* Put back the multibyte equivalent of the Unicode
1566 * value. */
1567 uni_mb = make_mbchar(uni, &uni_mb_len);
1568
1569 seq = (int *)nmalloc(uni_mb_len * sizeof(int));
1570
1571 for (i = 0; i < uni_mb_len; i++)
1572 seq[i] = (unsigned char)uni_mb[i];
1573
1574 unget_input(seq, uni_mb_len);
1575
1576 free(seq);
1577 free(uni_mb);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001578 }
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001579 } else
David Lawrence Ramseya5b1ca22006-05-28 17:09:49 +00001580#endif /* ENABLE_UTF8 */
1581
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001582 /* Put back the first keystroke. */
1583 unget_input(kbinput, 1);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001584
David Lawrence Ramseyad36bdc2006-12-02 17:22:21 +00001585 free(kbinput);
1586
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001587 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001588 * result. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00001589 *kbinput_len = get_key_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001590 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001591
1592 return retval;
1593}
1594
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001595#ifndef DISABLE_MOUSE
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001596/* Handle any mouse event that may have occurred. We currently handle
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001597 * releases/clicks of the first mouse button. If allow_shortcuts is
1598 * TRUE, releasing/clicking on a visible shortcut will put back the
1599 * keystroke associated with that shortcut. If NCURSES_MOUSE_VERSION is
1600 * at least 2, we also currently handle presses of the fourth mouse
1601 * button (upward rolls of the mouse wheel) by putting back the
1602 * keystrokes to move up, and presses of the fifth mouse button
1603 * (downward rolls of the mouse wheel) by putting back the keystrokes to
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001604 * move down. We also store the coordinates of a mouse event that needs
1605 * to be handled in mouse_x and mouse_y, relative to the entire screen.
1606 * Return -1 on error, 0 if the mouse event needs to be handled, 1 if
1607 * it's been handled by putting back keystrokes that need to be handled.
1608 * or 2 if it's been ignored. Assume that KEY_MOUSE has already been
1609 * read in. */
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001610int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001611{
1612 MEVENT mevent;
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001613 bool in_bottomwin;
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001614 subnfunc *f;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001615
1616 *mouse_x = -1;
1617 *mouse_y = -1;
1618
1619 /* First, get the actual mouse event. */
1620 if (getmouse(&mevent) == ERR)
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001621 return -1;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001622
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001623 /* Save the screen coordinates where the mouse event took place. */
1624 *mouse_x = mevent.x;
1625 *mouse_y = mevent.y;
David Lawrence Ramsey98e4d4f2006-06-28 21:54:55 +00001626
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001627 in_bottomwin = wenclose(bottomwin, *mouse_y, *mouse_x);
1628
David Lawrence Ramsey5fcf8bf2007-06-28 18:31:13 +00001629 /* Handle releases/clicks of the first mouse button. */
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001630 if (mevent.bstate & (BUTTON1_RELEASED | BUTTON1_CLICKED)) {
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001631 /* If we're allowing shortcuts, the current shortcut list is
1632 * being displayed on the last two lines of the screen, and the
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001633 * first mouse button was released on/clicked inside it, we need
1634 * to figure out which shortcut was released on/clicked and put
1635 * back the equivalent keystroke(s) for it. */
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001636 if (allow_shortcuts && !ISSET(NO_HELP) && in_bottomwin) {
David Lawrence Ramseybc653132007-05-22 17:20:28 +00001637 int i;
1638 /* The width of all the shortcuts, except for the last
1639 * two, in the shortcut list in bottomwin. */
1640 int j;
1641 /* The y-coordinate relative to the beginning of the
1642 * shortcut list in bottomwin. */
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001643 size_t currslen;
1644 /* The number of shortcuts in the current shortcut
1645 * list. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001646
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001647 /* Translate the mouse event coordinates so that they're
1648 * relative to bottomwin. */
1649 wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE);
1650
1651 /* Handle releases/clicks of the first mouse button on the
1652 * statusbar elsewhere. */
1653 if (*mouse_y == 0) {
1654 /* Restore the untranslated mouse event coordinates, so
1655 * that they're relative to the entire screen again. */
1656 *mouse_x = mevent.x;
1657 *mouse_y = mevent.y;
1658
1659 return 0;
1660 }
David Lawrence Ramseybc653132007-05-22 17:20:28 +00001661
1662 /* Calculate the y-coordinate relative to the beginning of
1663 * the shortcut list in bottomwin. */
1664 j = *mouse_y - 1;
1665
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001666 /* Get the shortcut lists' length. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001667 if (currmenu == MMAIN)
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001668 currslen = MAIN_VISIBLE;
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001669 else {
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001670 currslen = length_of_list(currmenu);
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001671
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001672 /* We don't show any more shortcuts than the main list
1673 * does. */
1674 if (currslen > MAIN_VISIBLE)
1675 currslen = MAIN_VISIBLE;
1676 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001677
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001678 /* Calculate the width of all of the shortcuts in the list
1679 * except for the last two, which are longer by (COLS % i)
1680 * columns so as to not waste space. */
1681 if (currslen < 2)
1682 i = COLS / (MAIN_VISIBLE / 2);
1683 else
1684 i = COLS / ((currslen / 2) + (currslen % 2));
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001685
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001686 /* Calculate the x-coordinate relative to the beginning of
1687 * the shortcut list in bottomwin, and add it to j. j
1688 * should now be the index in the shortcut list of the
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001689 * shortcut we released/clicked on. */
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001690 j = (*mouse_x / i) * 2 + j;
1691
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001692 /* Adjust j if we released on the last two shortcuts. */
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001693 if ((j >= currslen) && (*mouse_x % i < COLS % i))
1694 j -= 2;
1695
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001696 /* Ignore releases/clicks of the first mouse button beyond
1697 * the last shortcut. */
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001698 if (j >= currslen)
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001699 return 2;
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001700
1701 /* Go through the shortcut list to determine which shortcut
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001702 * we released/clicked on. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001703 f = allfuncs;
David Lawrence Ramseybc653132007-05-22 17:20:28 +00001704
Chris Allegrettac0b78722008-03-11 04:52:57 +00001705 for (; j > 0; j--) {
1706 if (f->next != NULL)
1707 f = f->next;
Chris Allegretta1d778232008-08-30 21:00:00 +00001708
1709 while (f->next != NULL && ((f->menus & currmenu) == 0
1710#ifndef DISABLE_HELP
1711 || strlen(f->help) == 0
1712#endif
1713 ))
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001714 f = f->next;
Chris Allegrettac0b78722008-03-11 04:52:57 +00001715 }
1716
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001717
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001718 /* And put back the equivalent key. */
1719 if (f != NULL) {
Chris Allegrettaa1171632009-01-19 19:10:39 +00001720 const sc *s = first_sc_for(currmenu, f->scfunc);
Chris Allegrettac0b78722008-03-11 04:52:57 +00001721 if (s != NULL)
1722 unget_kbinput(s->seq, s->type == META, FALSE);
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001723 }
1724 } else
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001725 /* Handle releases/clicks of the first mouse button that
1726 * aren't on the current shortcut list elsewhere. */
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001727 return 0;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001728 }
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001729#if NCURSES_MOUSE_VERSION >= 2
1730 /* Handle presses of the fourth mouse button (upward rolls of the
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001731 * mouse wheel) and presses of the fifth mouse button (downward
1732 * rolls of the mouse wheel) . */
1733 else if (mevent.bstate & (BUTTON4_PRESSED | BUTTON5_PRESSED)) {
David Lawrence Ramseydef60912007-12-08 16:59:13 +00001734 bool in_edit = wenclose(edit, *mouse_y, *mouse_x);
David Lawrence Ramseybc653132007-05-22 17:20:28 +00001735
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001736 if (in_bottomwin)
1737 /* Translate the mouse event coordinates so that they're
1738 * relative to bottomwin. */
1739 wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE);
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001740
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001741 if (in_edit || (in_bottomwin && *mouse_y == 0)) {
David Lawrence Ramseydef60912007-12-08 16:59:13 +00001742 int i;
1743
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001744 /* One upward roll of the mouse wheel is equivalent to
1745 * moving up three lines, and one downward roll of the mouse
1746 * wheel is equivalent to moving down three lines. */
1747 for (i = 0; i < 3; i++)
1748 unget_kbinput((mevent.bstate & BUTTON4_PRESSED) ?
Benno Schulenbergc4520d52014-02-22 19:36:35 +00001749 sc_seq_or(do_up_void, 0) : sc_seq_or(do_down_void, 0),
1750 FALSE, FALSE);
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001751
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001752 return 1;
1753 } else
1754 /* Ignore presses of the fourth mouse button and presses of
1755 * the fifth mouse buttons that aren't on the edit window or
1756 * the statusbar. */
1757 return 2;
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001758 }
1759#endif
David Lawrence Ramseyc8bde572007-06-28 16:38:00 +00001760
1761 /* Ignore all other mouse events. */
1762 return 2;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001763}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001764#endif /* !DISABLE_MOUSE */
1765
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001766/* Return the shortcut corresponding to the values of kbinput (the key
1767 * itself), meta_key (whether the key is a meta sequence), and func_key
1768 * (whether the key is a function key), if any. The shortcut will be
1769 * the first one in the list (control key, meta key sequence, function
1770 * key, other meta key sequence) for the corresponding function. For
1771 * example, passing in a meta key sequence that corresponds to a
1772 * function with a control key, a function key, and a meta key sequence
1773 * will return the control key corresponding to that function. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001774const sc *get_shortcut(int menu, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001775 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001776{
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001777 sc *s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001778
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001779#ifdef DEBUG
David Lawrence Ramsey23994bd2006-07-19 13:34:55 +00001780 fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %s, func_key = %s\n", *kbinput, *meta_key ? "TRUE" : "FALSE", *func_key ? "TRUE" : "FALSE");
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001781#endif
1782
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001783 /* Check for shortcuts. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001784 for (s = sclist; s != NULL; s = s->next) {
1785 if ((menu & s->menu)
1786 && ((s->type == META && *meta_key == TRUE && *kbinput == s->seq)
1787 || (s->type != META && *kbinput == s->seq))) {
1788#ifdef DEBUG
1789 fprintf (stderr, "matched seq \"%s\" and btw meta was %d (menus %d = %d)\n", s->keystr, *meta_key, menu, s->menu);
1790#endif
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001791 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001792 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001793 }
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001794#ifdef DEBUG
1795 fprintf (stderr, "matched nothing btw meta was %d\n", *meta_key);
1796#endif
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001797
1798 return NULL;
1799}
1800
Chris Allegretta0dc26dc2009-01-24 22:40:41 +00001801
1802/* Try to get a function back from a window. Just a wrapper so
Chris Allegretta2ad1de02012-12-30 19:20:10 +00001803 functions to need to create function_key meta_key blah blah
Chris Allegretta0dc26dc2009-01-24 22:40:41 +00001804 mmenu - what menu name to look through for valid funcs */
1805const subnfunc *getfuncfromkey(WINDOW *win)
1806{
1807 int kbinput;
1808 bool func_key = FALSE, meta_key = FALSE;
1809 const sc *s;
1810 const subnfunc *f;
1811
1812 kbinput = parse_kbinput(win, &meta_key, &func_key);
1813 if (kbinput == 0)
1814 return NULL;
1815
1816 s = get_shortcut(currmenu, &kbinput, &meta_key, &func_key);
1817 if (!s)
1818 return NULL;
1819
1820 f = sctofunc((sc *) s);
1821 return f;
1822
1823}
1824
1825
1826
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001827/* Move to (x, y) in win, and display a line of n spaces with the
1828 * current attributes. */
1829void blank_line(WINDOW *win, int y, int x, int n)
1830{
1831 wmove(win, y, x);
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00001832
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001833 for (; n > 0; n--)
1834 waddch(win, ' ');
1835}
1836
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001837/* Blank the first line of the top portion of the window. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001838void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001839{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001840 blank_line(topwin, 0, 0, COLS);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001841}
1842
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001843/* If the MORE_SPACE flag isn't set, blank the second line of the top
1844 * portion of the window. */
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00001845void blank_topbar(void)
1846{
1847 if (!ISSET(MORE_SPACE))
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001848 blank_line(topwin, 1, 0, COLS);
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00001849}
1850
David Lawrence Ramseyb159f942006-07-28 17:06:27 +00001851/* Blank all the lines of the middle portion of the window, i.e. the
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001852 * edit window. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001853void blank_edit(void)
1854{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001855 int i;
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00001856
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001857 for (i = 0; i < editwinrows; i++)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001858 blank_line(edit, i, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001859}
1860
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001861/* Blank the first line of the bottom portion of the window. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001862void blank_statusbar(void)
1863{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001864 blank_line(bottomwin, 0, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001865}
1866
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001867/* If the NO_HELP flag isn't set, blank the last two lines of the bottom
1868 * portion of the window. */
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00001869void blank_bottombars(void)
1870{
1871 if (!ISSET(NO_HELP)) {
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001872 blank_line(bottomwin, 1, 0, COLS);
1873 blank_line(bottomwin, 2, 0, COLS);
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00001874 }
1875}
1876
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001877/* Check if the number of keystrokes needed to blank the statusbar has
1878 * been pressed. If so, blank the statusbar, unless constant cursor
1879 * position display is on. */
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001880void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001881{
David Lawrence Ramsey100bc302006-05-27 18:06:11 +00001882 if (statusblank > 0) {
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001883 statusblank--;
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00001884
David Lawrence Ramsey100bc302006-05-27 18:06:11 +00001885 if (statusblank == 0 && !ISSET(CONST_UPDATE)) {
1886 blank_statusbar();
1887 wnoutrefresh(bottomwin);
1888 reset_cursor();
1889 wnoutrefresh(edit);
1890 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001891 }
1892}
1893
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001894/* Convert buf into a string that can be displayed on screen. The
1895 * caller wants to display buf starting with column start_col, and
1896 * extending for at most len columns. start_col is zero-based. len is
1897 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001898 * string is dynamically allocated, and should be freed. If dollars is
1899 * TRUE, the caller might put "$" at the beginning or end of the line if
1900 * it's too long. */
1901char *display_string(const char *buf, size_t start_col, size_t len, bool
1902 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001903{
1904 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00001905 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001906 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00001907 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001908 size_t alloc_len;
1909 /* The length of memory allocated for converted. */
1910 char *converted;
1911 /* The string we return. */
1912 size_t index;
1913 /* Current position in converted. */
David Lawrence Ramsey1f104f82006-02-03 03:51:51 +00001914 char *buf_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001915 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001916
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00001917 /* If dollars is TRUE, make room for the "$" at the end of the
1918 * line. */
1919 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
1920 len--;
1921
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001922 if (len == 0)
1923 return mallocstrcpy(NULL, "");
1924
David Lawrence Ramsey1f104f82006-02-03 03:51:51 +00001925 buf_mb = charalloc(mb_cur_max());
1926
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001927 start_index = actual_x(buf, start_col);
1928 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001929
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001930 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001931
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001932 /* Make sure there's enough room for the initial character, whether
1933 * it's a multibyte control character, a non-control multibyte
1934 * character, a tab character, or a null terminator. Rationale:
1935 *
1936 * multibyte control character followed by a null terminator:
1937 * 1 byte ('^') + mb_cur_max() bytes + 1 byte ('\0')
1938 * multibyte non-control character followed by a null terminator:
1939 * mb_cur_max() bytes + 1 byte ('\0')
1940 * tab character followed by a null terminator:
1941 * mb_cur_max() bytes + (tabsize - 1) bytes + 1 byte ('\0')
1942 *
1943 * Since tabsize has a minimum value of 1, it can substitute for 1
1944 * byte above. */
1945 alloc_len = (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
1946 converted = charalloc(alloc_len);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00001947
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001948 index = 0;
1949
David Lawrence Ramsey567d4712006-07-05 05:31:21 +00001950 if (buf[start_index] != '\0' && buf[start_index] != '\t' &&
1951 (column < start_col || (dollars && column > 0))) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001952 /* We don't display all of buf[start_index] since it starts to
1953 * the left of the screen. */
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001954 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001955
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001956 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00001957 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001958 char *ctrl_buf_mb = charalloc(mb_cur_max());
1959 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001960
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001961 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
1962 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00001963
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001964 for (i = 0; i < ctrl_buf_mb_len; i++)
1965 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001966
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001967 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001968
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001969 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00001970
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001971 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001972 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00001973 }
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00001974#ifdef ENABLE_UTF8
David Lawrence Ramseyd99b0e12006-05-19 17:50:01 +00001975 else if (using_utf8() && mbwidth(buf_mb) == 2) {
1976 if (column >= start_col) {
1977 converted[index++] = ' ';
1978 start_col++;
1979 }
1980
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00001981 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00001982 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001983
1984 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001985 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00001986#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001987 }
1988
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001989 while (buf[start_index] != '\0') {
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001990 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001991
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001992 /* Make sure there's enough room for the next character, whether
1993 * it's a multibyte control character, a non-control multibyte
1994 * character, a tab character, or a null terminator. */
1995 if (index + mb_cur_max() + tabsize + 1 >= alloc_len - 1) {
1996 alloc_len += (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
1997 converted = charealloc(converted, alloc_len);
1998 }
1999
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002000 /* If buf contains a tab character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002001 if (*buf_mb == '\t') {
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002002#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002003 if (ISSET(WHITESPACE_DISPLAY)) {
2004 int i;
2005
2006 for (i = 0; i < whitespace_len[0]; i++)
2007 converted[index++] = whitespace[i];
2008 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002009#endif
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00002010 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002011 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002012 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002013 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002014 start_col++;
2015 }
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002016 /* If buf contains a control character, interpret it. If buf
David Lawrence Ramsey61f56732005-07-21 22:12:03 +00002017 * contains an invalid multibyte control character, display it
2018 * as such.*/
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002019 } else if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002020 char *ctrl_buf_mb = charalloc(mb_cur_max());
2021 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002022
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002023 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002024 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002025
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002026 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2027 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002028
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002029 for (i = 0; i < ctrl_buf_mb_len; i++)
2030 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002031
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002032 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002033
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002034 free(ctrl_buf_mb);
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002035 /* If buf contains a space character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002036 } else if (*buf_mb == ' ') {
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002037#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002038 if (ISSET(WHITESPACE_DISPLAY)) {
2039 int i;
2040
2041 for (i = whitespace_len[0]; i < whitespace_len[0] +
2042 whitespace_len[1]; i++)
2043 converted[index++] = whitespace[i];
2044 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002045#endif
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00002046 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002047 start_col++;
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00002048 /* If buf contains a non-control character, interpret it. If
2049 * buf contains an invalid multibyte non-control character,
2050 * display it as such. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002051 } else {
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00002052 char *nctrl_buf_mb = charalloc(mb_cur_max());
2053 int nctrl_buf_mb_len, i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002054
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00002055 nctrl_buf_mb = mbrep(buf_mb, nctrl_buf_mb,
2056 &nctrl_buf_mb_len);
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002057
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00002058 for (i = 0; i < nctrl_buf_mb_len; i++)
2059 converted[index++] = nctrl_buf_mb[i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002060
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00002061 start_col += mbwidth(nctrl_buf_mb);
2062
2063 free(nctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002064 }
2065
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002066 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002067 }
2068
David Lawrence Ramsey6a0d5b82005-06-13 14:00:22 +00002069 free(buf_mb);
2070
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00002071 assert(alloc_len >= index + 1);
2072
David Lawrence Ramseye54f1c42006-10-29 21:14:53 +00002073 /* Null-terminate converted. */
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00002074 converted[index] = '\0';
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002075
2076 /* Make sure converted takes up no more than len columns. */
2077 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002078 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002079
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002080 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002081}
2082
David Lawrence Ramsey4ea2eac2006-07-09 00:52:16 +00002083/* If path is NULL, we're in normal editing mode, so display the current
2084 * version of nano, the current filename, and whether the current file
2085 * has been modified on the titlebar. If path isn't NULL, we're in the
2086 * file browser, and path contains the directory to start the file
2087 * browser in, so display the current version of nano and the contents
2088 * of path on the titlebar. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00002089void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002090{
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002091 int space = COLS;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002092 /* The space we have available for display. */
David Lawrence Ramsey3c43d3d2006-03-30 01:18:29 +00002093 size_t verlen = strlenpt(PACKAGE_STRING) + 1;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002094 /* The length of the version message in columns, plus one for
2095 * padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002096 const char *prefix;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002097 /* "DIR:", "File:", or "New Buffer". Goes before filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002098 size_t prefixlen;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002099 /* The length of the prefix in columns, plus one for padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002100 const char *state;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002101 /* "Modified", "View", or "". Shows the state of this
2102 * buffer. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002103 size_t statelen = 0;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002104 /* The length of the state in columns, or the length of
David Lawrence Ramsey4ea2eac2006-07-09 00:52:16 +00002105 * "Modified" if the state is blank and we're not in the file
2106 * browser. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002107 char *exppath = NULL;
David Lawrence Ramsey345a5b82006-07-04 03:47:36 +00002108 /* The filename, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002109 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002110 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002111 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002112 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002113
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002114 assert(path != NULL || openfile->filename != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002115
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002116 wattron(topwin, reverse_attr);
David Lawrence Ramsey85ffaee2006-07-02 18:29:49 +00002117
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002118 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002119
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002120 /* space has to be at least 4: two spaces before the version message,
2121 * at least one character of the version message, and one space
2122 * after the version message. */
2123 if (space < 4)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002124 space = 0;
2125 else {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002126 /* Limit verlen to 1/3 the length of the screen in columns,
2127 * minus three columns for spaces. */
2128 if (verlen > (COLS / 3) - 3)
2129 verlen = (COLS / 3) - 3;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002130 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002131
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002132 if (space >= 4) {
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002133 /* Add a space after the version message, and account for both
2134 * it and the two spaces before it. */
David Lawrence Ramsey3c43d3d2006-03-30 01:18:29 +00002135 mvwaddnstr(topwin, 0, 2, PACKAGE_STRING,
2136 actual_x(PACKAGE_STRING, verlen));
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002137 verlen += 3;
2138
2139 /* Account for the full length of the version message. */
2140 space -= verlen;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002141 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002142
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002143#ifndef DISABLE_BROWSER
2144 /* Don't display the state if we're in the file browser. */
2145 if (path != NULL)
2146 state = "";
2147 else
2148#endif
2149 state = openfile->modified ? _("Modified") : ISSET(VIEW_MODE) ?
2150 _("View") : "";
2151
David Lawrence Ramsey1904f512007-07-01 21:33:17 +00002152 statelen = strlenpt((*state == '\0' && path == NULL) ?
David Lawrence Ramseye3281692006-07-09 00:50:23 +00002153 _("Modified") : state);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002154
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002155 /* If possible, add a space before state. */
2156 if (space > 0 && statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002157 statelen++;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002158 else
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002159 goto the_end;
2160
2161#ifndef DISABLE_BROWSER
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002162 /* path should be a directory if we're in the file browser. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002163 if (path != NULL)
2164 prefix = _("DIR:");
2165 else
2166#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002167 if (openfile->filename[0] == '\0') {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002168 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002169 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002170 } else
2171 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002172
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002173 prefixlen = strnlenpt(prefix, space - statelen) + 1;
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002174
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002175 /* If newfie is FALSE, add a space after prefix. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002176 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002177 prefixlen++;
2178
David Lawrence Ramsey4ea2eac2006-07-09 00:52:16 +00002179 /* If we're not in the file browser, set path to the current
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002180 * filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002181 if (path == NULL)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002182 path = openfile->filename;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002183
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002184 /* Account for the full lengths of the prefix and the state. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002185 if (space >= prefixlen + statelen)
2186 space -= prefixlen + statelen;
2187 else
2188 space = 0;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002189 /* space is now the room we have for the filename. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002190
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002191 if (!newfie) {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002192 size_t lenpt = strlenpt(path), start_col;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002193
David Lawrence Ramsey8125e082006-11-25 22:27:22 +00002194 /* Don't set dots to TRUE if we have fewer than eight columns
2195 * (i.e. one column for padding, plus seven columns for a
2196 * filename). */
David Lawrence Ramsey49172ca2006-07-13 02:10:27 +00002197 dots = (space >= 8 && lenpt >= space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002198
2199 if (dots) {
2200 start_col = lenpt - space + 3;
2201 space -= 3;
2202 } else
2203 start_col = 0;
2204
2205 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002206 }
2207
David Lawrence Ramsey85ffaee2006-07-02 18:29:49 +00002208 /* If dots is TRUE, we will display something like "File:
2209 * ...ename". */
2210 if (dots) {
2211 mvwaddnstr(topwin, 0, verlen - 1, prefix, actual_x(prefix,
2212 prefixlen));
2213 if (space <= -3 || newfie)
2214 goto the_end;
2215 waddch(topwin, ' ');
2216 waddnstr(topwin, "...", space + 3);
2217 if (space <= 0)
2218 goto the_end;
2219 waddstr(topwin, exppath);
2220 } else {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002221 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2222 /* The length of the expanded filename. */
2223
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002224 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002225 mvwaddnstr(topwin, 0, verlen + ((space - exppathlen) / 3),
2226 prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002227 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002228 waddch(topwin, ' ');
2229 waddstr(topwin, exppath);
2230 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002231 }
2232
2233 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002234 free(exppath);
2235
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002236 if (state[0] != '\0') {
David Lawrence Ramsey3d12f0f2005-10-26 23:14:59 +00002237 if (statelen >= COLS - 1)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002238 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
2239 else {
David Lawrence Ramseycaa86592005-07-10 23:57:32 +00002240 assert(COLS - statelen - 1 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002241
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002242 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002243 actual_x(state, statelen));
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002244 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002245 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002246
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002247 wattroff(topwin, reverse_attr);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002248
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002249 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002250 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002251 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002252}
2253
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002254/* Mark the current file as modified if it isn't already, and then
2255 * update the titlebar to display the file's new status. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002256void set_modified(void)
2257{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002258 if (!openfile->modified) {
2259 openfile->modified = TRUE;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002260 titlebar(NULL);
Chris Allegretta21f73f92013-01-03 03:07:27 +00002261#ifndef NANO_TINY
Chris Allegrettad70c7f32013-01-03 03:36:20 +00002262 if (ISSET(LOCKING)) {
Chris Allegrettad2f29d02014-01-26 04:09:04 +00002263 if (!strcmp(openfile->filename, ""))
2264 return;
2265 else if (openfile->lock_filename == NULL) {
Chris Allegrettad70c7f32013-01-03 03:36:20 +00002266 /* Translators: Try to keep this at most 80 characters. */
2267 statusbar(_("Warning: Modifying a file which is not locked, check directory permission?"));
2268 } else {
2269 write_lockfile(openfile->lock_filename,
2270 get_full_path(openfile->filename), TRUE);
2271 }
2272 }
Chris Allegretta21f73f92013-01-03 03:07:27 +00002273#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002274 }
2275}
2276
David Lawrence Ramsey5593e202005-06-28 19:49:15 +00002277/* Display a message on the statusbar, and set disable_cursorpos to
2278 * TRUE, so that the message won't be immediately overwritten if
2279 * constant cursor position display is on. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002280void statusbar(const char *msg, ...)
2281{
2282 va_list ap;
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002283 char *bar, *foo;
2284 size_t start_x, foo_len;
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002285#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002286 bool old_whitespace;
2287#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002288
2289 va_start(ap, msg);
2290
2291 /* Curses mode is turned off. If we use wmove() now, it will muck
2292 * up the terminal settings. So we just use vfprintf(). */
David Lawrence Ramseyf70f67b2006-06-03 17:31:52 +00002293 if (isendwin()) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002294 vfprintf(stderr, msg, ap);
2295 va_end(ap);
2296 return;
2297 }
2298
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002299 blank_statusbar();
2300
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002301#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002302 old_whitespace = ISSET(WHITESPACE_DISPLAY);
2303 UNSET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002304#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002305 bar = charalloc(mb_cur_max() * (COLS - 3));
2306 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
2307 va_end(ap);
2308 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002309#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002310 if (old_whitespace)
2311 SET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002312#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002313 free(bar);
2314 foo_len = strlenpt(foo);
2315 start_x = (COLS - foo_len - 4) / 2;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002316
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002317 wmove(bottomwin, 0, start_x);
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002318 wattron(bottomwin, reverse_attr);
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002319 waddstr(bottomwin, "[ ");
2320 waddstr(bottomwin, foo);
2321 free(foo);
2322 waddstr(bottomwin, " ]");
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002323 wattroff(bottomwin, reverse_attr);
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002324 wnoutrefresh(bottomwin);
2325 reset_cursor();
2326 wnoutrefresh(edit);
2327 /* Leave the cursor at its position in the edit window, not in
2328 * the statusbar. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002329
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002330 disable_cursorpos = TRUE;
David Lawrence Ramseyc6618532005-06-17 22:33:15 +00002331
2332 /* If we're doing quick statusbar blanking, and constant cursor
2333 * position display is off, blank the statusbar after only one
David Lawrence Ramseyce862362006-05-21 21:23:21 +00002334 * keystroke. Otherwise, blank it after twenty-six keystrokes, as
2335 * Pico does. */
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002336 statusblank =
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002337#ifndef NANO_TINY
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002338 ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 :
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002339#endif
David Lawrence Ramseyce862362006-05-21 21:23:21 +00002340 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002341}
2342
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002343/* Display the shortcut list in s on the last two rows of the bottom
2344 * portion of the window. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002345void bottombars(int menu)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002346{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002347 size_t i, colwidth, slen;
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002348 subnfunc *f;
2349 const sc *s;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002350
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002351 if (ISSET(NO_HELP))
2352 return;
2353
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002354 if (menu == MMAIN) {
Chris Allegretta6232d662002-05-12 19:52:15 +00002355 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002356
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002357 assert(slen <= length_of_list(menu));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002358 } else {
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002359 slen = length_of_list(menu);
Chris Allegretta6232d662002-05-12 19:52:15 +00002360
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002361 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002362 if (slen > MAIN_VISIBLE)
2363 slen = MAIN_VISIBLE;
2364 }
2365
David Lawrence Ramseye806ab82006-04-18 16:13:35 +00002366 /* There will be this many characters per column, except for the
2367 * last two, which will be longer by (COLS % colwidth) columns so as
2368 * to not waste space. We need at least three columns to display
2369 * anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002370 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002371
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002372 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002373
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002374#ifdef DEBUG
2375 fprintf(stderr, "In bottombars, and slen == \"%d\"\n", (int) slen);
2376#endif
Chris Allegretta658399a2001-06-14 02:54:22 +00002377
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002378 for (f = allfuncs, i = 0; i < slen && f != NULL; f = f->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +00002379
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002380#ifdef DEBUG
2381 fprintf(stderr, "Checking menu items....");
2382#endif
2383 if ((f->menus & menu) == 0)
2384 continue;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002385
Chris Allegretta0018d8e2008-03-13 08:23:52 +00002386 if (!f->desc || strlen(f->desc) == 0)
Chris Allegrettaeb643142008-03-12 04:44:14 +00002387 continue;
2388
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002389#ifdef DEBUG
Chris Allegretta17436ce2008-03-11 03:03:53 +00002390 fprintf(stderr, "found one! f->menus = %d, desc = \"%s\"\n", f->menus, f->desc);
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002391#endif
2392 s = first_sc_for(menu, f->scfunc);
2393 if (s == NULL) {
2394#ifdef DEBUG
2395 fprintf(stderr, "Whoops, guess not, no shortcut key found for func!\n");
2396#endif
2397 continue;
2398 }
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002399 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002400#ifdef DEBUG
2401 fprintf(stderr, "Calling onekey with keystr \"%s\" and desc \"%s\"\n", s->keystr, f->desc);
2402#endif
Chris Allegretta1fb25fd2008-03-18 03:06:27 +00002403 onekey(s->keystr, _(f->desc), colwidth + (COLS % colwidth));
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002404 i++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002405 }
2406
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002407 wnoutrefresh(bottomwin);
2408 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002409 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002410}
2411
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002412/* Write a shortcut key to the help area at the bottom of the window.
2413 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2414 * to write at most len characters, even if len is very small and
2415 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2416 * the whole string! We do not bother padding the entry with blanks. */
2417void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002418{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002419 size_t keystroke_len = strlenpt(keystroke) + 1;
2420
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002421 assert(keystroke != NULL && desc != NULL);
2422
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002423 wattron(bottomwin, reverse_attr);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002424 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002425 wattroff(bottomwin, reverse_attr);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002426
2427 if (len > keystroke_len)
2428 len -= keystroke_len;
2429 else
2430 len = 0;
2431
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002432 if (len > 0) {
2433 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002434 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002435 }
2436}
2437
David Lawrence Ramsey2b9d6a02005-11-01 17:45:31 +00002438/* Reset current_y, based on the position of current, and put the cursor
2439 * in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002440void reset_cursor(void)
2441{
Chris Allegretta05417a22009-08-17 07:52:10 +00002442 size_t xpt;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002443 /* If we haven't opened any files yet, put the cursor in the top
2444 * left corner of the edit window and get out. */
David Lawrence Ramseydbcaa3b2005-07-08 20:59:24 +00002445 if (openfile == NULL) {
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002446 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002447 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002448 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002449
Chris Allegretta05417a22009-08-17 07:52:10 +00002450 xpt = xplustabs();
David Lawrence Ramsey964722a2006-05-26 03:02:50 +00002451
Chris Allegretta05417a22009-08-17 07:52:10 +00002452 if (ISSET(SOFTWRAP)) {
Chris Allegretta05417a22009-08-17 07:52:10 +00002453 filestruct *tmp;
Chris Allegretta6f083322009-11-11 06:00:33 +00002454 openfile->current_y = 0;
Chris Allegretta05417a22009-08-17 07:52:10 +00002455
Chris Allegretta6f083322009-11-11 06:00:33 +00002456 for (tmp = openfile->edittop; tmp && tmp != openfile->current; tmp = tmp->next)
2457 openfile->current_y += 1 + strlenpt(tmp->data) / COLS;
2458
2459 openfile->current_y += xplustabs() / COLS;
Chris Allegretta05417a22009-08-17 07:52:10 +00002460 if (openfile->current_y < editwinrows)
Chris Allegretta6f083322009-11-11 06:00:33 +00002461 wmove(edit, openfile->current_y, xpt % COLS);
Chris Allegretta05417a22009-08-17 07:52:10 +00002462 } else {
2463 openfile->current_y = openfile->current->lineno -
2464 openfile->edittop->lineno;
2465
2466 if (openfile->current_y < editwinrows)
2467 wmove(edit, openfile->current_y, xpt - get_page_start(xpt));
2468 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002469}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002470
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002471/* edit_draw() takes care of the job of actually painting a line into
2472 * the edit window. fileptr is the line to be painted, at row line of
2473 * the window. converted is the actual string to be written to the
2474 * window, with tabs and control characters replaced by strings of
2475 * regular characters. start is the column number of the first
2476 * character of this page. That is, the first character of converted
2477 * corresponds to character number actual_x(fileptr->data, start) of the
2478 * line. */
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002479void edit_draw(filestruct *fileptr, const char *converted, int
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002480 line, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002481{
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002482#if !defined(NANO_TINY) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002483 size_t startpos = actual_x(fileptr->data, start);
2484 /* The position in fileptr->data of the leftmost character
2485 * that displays at least partially on the window. */
2486 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2487 /* The position in fileptr->data of the first character that is
2488 * completely off the window to the right.
2489 *
2490 * Note that endpos might be beyond the null terminator of the
2491 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002492#endif
2493
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002494 assert(openfile != NULL && fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002495 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002496
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002497 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002498 * just the text that needs it). */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002499 mvwaddstr(edit, line, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002500
Chris Allegretta7dd77682001-12-08 19:52:28 +00002501#ifdef ENABLE_COLOR
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002502 /* If color syntaxes are available and turned on, we need to display
2503 * them. */
2504 if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
2505 const colortype *tmpcolor = openfile->colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002506
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002507 /* Set up multi-line color data for this line if it's not yet calculated */
Chris Allegretta364763f2009-02-03 05:05:58 +00002508 if (fileptr->multidata == NULL && openfile->syntax
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002509 && openfile->syntax->nmultis > 0) {
Chris Allegretta22c83ec2013-03-17 22:09:38 +00002510 int i;
Chris Allegretta5a018f02009-11-29 06:13:22 +00002511 fileptr->multidata = (short *) nmalloc(openfile->syntax->nmultis * sizeof(short));
Chris Allegretta22c83ec2013-03-17 22:09:38 +00002512 for (i = 0; i < openfile->syntax->nmultis; i++)
Chris Allegretta364763f2009-02-03 05:05:58 +00002513 fileptr->multidata[i] = -1; /* Assue this applies until we know otherwise */
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002514 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002515 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2516 int x_start;
2517 /* Starting column for mvwaddnstr. Zero-based. */
2518 int paintlen;
David Lawrence Ramsey2ea7fb02006-08-02 18:41:55 +00002519 /* Number of chars to paint on this line. There are
2520 * COLS characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002521 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002522 /* Index in converted where we paint. */
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002523 regmatch_t startmatch;
2524 /* Match position for start_regex. */
2525 regmatch_t endmatch;
2526 /* Match position for end_regex. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002527
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002528 if (tmpcolor->bright)
2529 wattron(edit, A_BOLD);
2530 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramseyb0e04c02005-12-08 07:24:54 +00002531 /* Two notes about regexec(). A return value of zero means
2532 * that there is a match. Also, rm_eo is the first
2533 * non-matching character after the match. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002534
Chris Allegretta22c83ec2013-03-17 22:09:38 +00002535 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002536 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002537 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002538
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002539 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002540 * last match. Even though two matches may overlap, we
David Lawrence Ramsey2ef7dae2006-05-26 11:58:37 +00002541 * want to ignore them, so that we can highlight e.g. C
2542 * strings correctly. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002543 while (k < endpos) {
2544 /* Note the fifth parameter to regexec(). It says
2545 * not to match the beginning-of-line character
David Lawrence Ramsey2ef7dae2006-05-26 11:58:37 +00002546 * unless k is zero. If regexec() returns
2547 * REG_NOMATCH, there are no more matches in the
2548 * line. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002549 if (regexec(tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002550 &startmatch, (k == 0) ? 0 : REG_NOTBOL) ==
2551 REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002552 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002553 /* Translate the match to the beginning of the
2554 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002555 startmatch.rm_so += k;
2556 startmatch.rm_eo += k;
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002557
2558 /* Skip over a zero-length regex match. */
2559 if (startmatch.rm_so == startmatch.rm_eo)
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002560 startmatch.rm_eo++;
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002561 else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002562 startmatch.rm_eo > startpos) {
David Lawrence Ramseyb02a1952006-05-08 16:25:12 +00002563 x_start = (startmatch.rm_so <= startpos) ? 0 :
2564 strnlenpt(fileptr->data,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002565 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002566
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002567 index = actual_x(converted, x_start);
2568
2569 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00002570 strnlenpt(fileptr->data,
2571 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002572
2573 assert(0 <= x_start && 0 <= paintlen);
2574
Chris Allegretta22c83ec2013-03-17 22:09:38 +00002575 mvwaddnstr(edit, line, x_start, converted +
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002576 index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002577 }
Chris Allegretta22c83ec2013-03-17 22:09:38 +00002578 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002579 }
Chris Allegretta56a295b2009-02-07 14:48:30 +00002580 } else if (fileptr->multidata != NULL && fileptr->multidata[tmpcolor->id] != CNONE) {
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002581 /* This is a multi-line regex. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002582 * First, we have to see if the beginning of the line is
2583 * colored by a start on an earlier line, and an end on
2584 * this line or later.
2585 *
2586 * We find the first line before fileptr matching the
2587 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002588 * end, then go to step two. Otherwise, find the next
2589 * line after start_line matching the end. If that line
2590 * is not before fileptr, then paint the beginning of
2591 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002592 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002593 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002594 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002595 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002596 const filestruct *end_line;
Chris Allegretta364763f2009-02-03 05:05:58 +00002597 short md = fileptr->multidata[tmpcolor->id];
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002598
Chris Allegretta364763f2009-02-03 05:05:58 +00002599 if (md == -1)
Chris Allegretta56a295b2009-02-07 14:48:30 +00002600 fileptr->multidata[tmpcolor->id] = CNONE; /* until we find out otherwise */
Chris Allegretta364763f2009-02-03 05:05:58 +00002601 else if (md == CNONE)
2602 continue;
2603 else if (md == CWHOLELINE) {
2604 mvwaddnstr(edit, line, 0, converted, -1);
2605 continue;
Chris Allegretta803379c2009-02-07 07:09:31 +00002606 } else if (md == CBEGINBEFORE) {
2607 regexec(tmpcolor->end, fileptr->data, 1, &endmatch, 0);
2608 paintlen = actual_x(converted, strnlenpt(fileptr->data,
2609 endmatch.rm_eo) - start);
2610 mvwaddnstr(edit, line, 0, converted, paintlen);
2611 continue;
Chris Allegretta364763f2009-02-03 05:05:58 +00002612 }
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002613
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002614 while (start_line != NULL && regexec(tmpcolor->start,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002615 start_line->data, 1, &startmatch, 0) ==
2616 REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002617 /* If there is an end on this line, there is no need
2618 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002619 if (regexec(tmpcolor->end, start_line->data, 0,
2620 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002621 goto step_two;
2622 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002623 }
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002624
2625 /* Skip over a zero-length regex match. */
2626 if (startmatch.rm_so == startmatch.rm_eo)
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002627 startmatch.rm_eo++;
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002628 else {
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002629 /* No start found, so skip to the next step. */
2630 if (start_line == NULL)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002631 goto step_two;
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002632 /* Now start_line is the first line before fileptr
2633 * containing a start match. Is there a start on
2634 * this line not followed by an end on this line? */
2635 start_col = 0;
2636 while (TRUE) {
2637 start_col += startmatch.rm_so;
2638 startmatch.rm_eo -= startmatch.rm_so;
2639 if (regexec(tmpcolor->end, start_line->data +
2640 start_col + startmatch.rm_eo, 0, NULL,
2641 (start_col + startmatch.rm_eo == 0) ?
2642 0 : REG_NOTBOL) == REG_NOMATCH)
2643 /* No end found after this start. */
2644 break;
2645 start_col++;
2646 if (regexec(tmpcolor->start, start_line->data +
2647 start_col, 1, &startmatch,
2648 REG_NOTBOL) == REG_NOMATCH)
2649 /* No later start on this line. */
2650 goto step_two;
2651 }
2652 /* Indeed, there is a start not followed on this
2653 * line by an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002654
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002655 /* We have already checked that there is no end
2656 * before fileptr and after the start. Is there an
2657 * end after the start at all? We don't paint
2658 * unterminated starts. */
2659 end_line = fileptr;
2660 while (end_line != NULL && regexec(tmpcolor->end,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002661 end_line->data, 1, &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002662 end_line = end_line->next;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002663
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002664 /* No end found, or it is too early. */
2665 if (end_line == NULL || (end_line == fileptr &&
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002666 endmatch.rm_eo <= startpos))
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002667 goto step_two;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002668
David Lawrence Ramseycbab2732006-08-02 18:38:45 +00002669 /* Now paint the start of fileptr. If the start of
2670 * fileptr is on a different line from the end,
2671 * paintlen is -1, meaning that everything on the
2672 * line gets painted. Otherwise, paintlen is the
2673 * expanded location of the end of the match minus
2674 * the expanded location of the beginning of the
2675 * page. */
Chris Allegretta364763f2009-02-03 05:05:58 +00002676 if (end_line != fileptr) {
David Lawrence Ramsey1c9dd102006-11-21 17:05:04 +00002677 paintlen = -1;
Chris Allegretta364763f2009-02-03 05:05:58 +00002678 fileptr->multidata[tmpcolor->id] = CWHOLELINE;
2679 } else {
David Lawrence Ramsey1c9dd102006-11-21 17:05:04 +00002680 paintlen = actual_x(converted,
2681 strnlenpt(fileptr->data,
2682 endmatch.rm_eo) - start);
Chris Allegretta364763f2009-02-03 05:05:58 +00002683 fileptr->multidata[tmpcolor->id] = CBEGINBEFORE;
2684 }
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002685 mvwaddnstr(edit, line, 0, converted, paintlen);
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002686 step_two:
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002687 /* Second step, we look for starts on this line. */
2688 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002689
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002690 while (start_col < endpos) {
2691 if (regexec(tmpcolor->start, fileptr->data +
2692 start_col, 1, &startmatch, (start_col ==
2693 0) ? 0 : REG_NOTBOL) == REG_NOMATCH ||
2694 start_col + startmatch.rm_so >= endpos)
2695 /* No more starts on this line. */
2696 break;
2697 /* Translate the match to be relative to the
2698 * beginning of the line. */
2699 startmatch.rm_so += start_col;
2700 startmatch.rm_eo += start_col;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002701
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002702 x_start = (startmatch.rm_so <= startpos) ? 0 :
2703 strnlenpt(fileptr->data,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002704 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002705
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002706 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002707
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002708 if (regexec(tmpcolor->end, fileptr->data +
2709 startmatch.rm_eo, 1, &endmatch,
2710 (startmatch.rm_eo == 0) ? 0 :
2711 REG_NOTBOL) == 0) {
2712 /* Translate the end match to be relative to
2713 * the beginning of the line. */
2714 endmatch.rm_so += startmatch.rm_eo;
2715 endmatch.rm_eo += startmatch.rm_eo;
2716 /* There is an end on this line. But does
2717 * it appear on this page, and is the match
2718 * more than zero characters long? */
2719 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002720 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002721 paintlen = actual_x(converted + index,
2722 strnlenpt(fileptr->data,
2723 endmatch.rm_eo) - start -
2724 x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002725
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002726 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002727
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002728 mvwaddnstr(edit, line, x_start,
2729 converted + index, paintlen);
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002730 if (paintlen > 0)
Chris Allegretta364763f2009-02-03 05:05:58 +00002731 fileptr->multidata[tmpcolor->id] = CSTARTENDHERE;
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002732
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002733 }
2734 } else {
2735 /* There is no end on this line. But we
2736 * haven't yet looked for one on later
2737 * lines. */
2738 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002739
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002740 while (end_line != NULL &&
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002741 regexec(tmpcolor->end, end_line->data,
2742 0, NULL, 0) == REG_NOMATCH)
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002743 end_line = end_line->next;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002744
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002745 if (end_line != NULL) {
2746 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002747
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002748 mvwaddnstr(edit, line, x_start,
2749 converted + index, -1);
2750 /* We painted to the end of the line, so
2751 * don't bother checking any more
2752 * starts. */
Chris Allegretta364763f2009-02-03 05:05:58 +00002753 fileptr->multidata[tmpcolor->id] = CENDAFTER;
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002754 break;
2755 }
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002756 }
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002757 start_col = startmatch.rm_so + 1;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002758 }
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002759 }
2760 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002761
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002762 wattroff(edit, A_BOLD);
2763 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002764 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002765 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002766#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002767
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002768#ifndef NANO_TINY
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002769 /* If the mark is on, we need to display it. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002770 if (openfile->mark_set && (fileptr->lineno <=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002771 openfile->mark_begin->lineno || fileptr->lineno <=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002772 openfile->current->lineno) && (fileptr->lineno >=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002773 openfile->mark_begin->lineno || fileptr->lineno >=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002774 openfile->current->lineno)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002775 /* fileptr is at least partially selected. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002776 const filestruct *top;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002777 /* Either current or mark_begin, whichever is first. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002778 size_t top_x;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002779 /* current_x or mark_begin_x, corresponding to top. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002780 const filestruct *bot;
2781 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002782 int x_start;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002783 /* Starting column for mvwaddnstr(). Zero-based. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002784 int paintlen;
David Lawrence Ramseyc6bef762006-08-02 19:13:31 +00002785 /* Number of characters to paint on this line. There are
2786 * COLS characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002787 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002788 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002789
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00002790 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002791
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002792 if (top->lineno < fileptr->lineno || top_x < startpos)
2793 top_x = startpos;
2794 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2795 bot_x = endpos;
2796
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002797 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002798 if (top_x < endpos && bot_x > startpos) {
2799 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002800
2801 /* x_start is the expanded location of the beginning of the
2802 * mark minus the beginning of the page. */
2803 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002804
David Lawrence Ramseycbab2732006-08-02 18:38:45 +00002805 /* If the end of the mark is off the page, paintlen is -1,
2806 * meaning that everything on the line gets painted.
2807 * Otherwise, paintlen is the expanded location of the end
2808 * of the mark minus the expanded location of the beginning
2809 * of the mark. */
David Lawrence Ramsey1c9dd102006-11-21 17:05:04 +00002810 if (bot_x >= endpos)
2811 paintlen = -1;
2812 else
2813 paintlen = strnlenpt(fileptr->data, bot_x) - (x_start +
2814 start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002815
2816 /* If x_start is before the beginning of the page, shift
2817 * paintlen x_start characters to compensate, and put
2818 * x_start at the beginning of the page. */
2819 if (x_start < 0) {
2820 paintlen += x_start;
2821 x_start = 0;
2822 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002823
2824 assert(x_start >= 0 && x_start <= strlen(converted));
2825
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002826 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002827
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002828 if (paintlen > 0)
2829 paintlen = actual_x(converted + index, paintlen);
2830
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002831 wattron(edit, reverse_attr);
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002832 mvwaddnstr(edit, line, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00002833 paintlen);
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002834 wattroff(edit, reverse_attr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002835 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002836 }
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002837#endif /* !NANO_TINY */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002838}
2839
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002840/* Just update one line in the edit buffer. This is basically a wrapper
David Lawrence Ramseyb3c6b402005-11-07 06:20:02 +00002841 * for edit_draw(). The line will be displayed starting with
Chris Allegretta05417a22009-08-17 07:52:10 +00002842 * fileptr->data[index]. Likely arguments are current_x or zero.
2843 * Returns: Number of additiona lines consumed (needed for SOFTWRAP)
2844 */
2845int update_line(filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002846{
Chris Allegretta05417a22009-08-17 07:52:10 +00002847 int line = 0;
2848 int extralinesused = 0;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002849 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002850 char *converted;
2851 /* fileptr->data converted to have tabs and control characters
2852 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002853 size_t page_start;
Chris Allegretta05417a22009-08-17 07:52:10 +00002854 filestruct *tmp;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002855
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002856 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002857
Chris Allegretta05417a22009-08-17 07:52:10 +00002858 if (ISSET(SOFTWRAP)) {
Chris Allegretta139934a2009-08-30 03:50:16 +00002859 for (tmp = openfile->edittop; tmp && tmp != fileptr; tmp = tmp->next) {
Chris Allegretta05417a22009-08-17 07:52:10 +00002860 line += 1 + (strlenpt(tmp->data) / COLS);
Chris Allegretta05417a22009-08-17 07:52:10 +00002861 }
2862 } else
2863 line = fileptr->lineno - openfile->edittop->lineno;
2864
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002865 if (line < 0 || line >= editwinrows)
Chris Allegrettad233e7e2009-09-15 04:51:09 +00002866 return 1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002867
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002868 /* First, blank out the line. */
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002869 blank_line(edit, line, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002870
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002871 /* Next, convert variables that index the line to their equivalent
2872 * positions in the expanded line. */
Chris Allegretta05417a22009-08-17 07:52:10 +00002873 if (ISSET(SOFTWRAP))
2874 index = 0;
2875 else
2876 index = strnlenpt(fileptr->data, index);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002877 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002878
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002879 /* Expand the line, replacing tabs with spaces, and control
2880 * characters with their displayed forms. */
Chris Allegretta6f083322009-11-11 06:00:33 +00002881 converted = display_string(fileptr->data, page_start, COLS, !ISSET(SOFTWRAP));
2882
2883#ifdef DEBUG
2884 if (ISSET(SOFTWRAP) && strlen(converted) >= COLS - 2)
2885 fprintf(stderr, "update_line(): converted(1) line = %s\n", converted);
2886#endif
2887
Robert Siemborski53875912000-06-16 04:25:30 +00002888
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002889 /* Paint the line. */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002890 edit_draw(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002891 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002892
Chris Allegretta05417a22009-08-17 07:52:10 +00002893 if (!ISSET(SOFTWRAP)) {
2894 if (page_start > 0)
2895 mvwaddch(edit, line, 0, '$');
2896 if (strlenpt(fileptr->data) > page_start + COLS)
2897 mvwaddch(edit, line, COLS - 1, '$');
2898 } else {
2899 int full_length = strlenpt(fileptr->data);
Chris Allegretta6f083322009-11-11 06:00:33 +00002900 for (index += COLS; index <= full_length && line < editwinrows; index += COLS) {
Chris Allegretta05417a22009-08-17 07:52:10 +00002901 line++;
2902#ifdef DEBUG
Chris Allegretta6f083322009-11-11 06:00:33 +00002903 fprintf(stderr, "update_line(): Softwrap code, moving to %d index %lu\n", line, (unsigned long) index);
Chris Allegretta05417a22009-08-17 07:52:10 +00002904#endif
2905 blank_line(edit, line, 0, COLS);
2906
2907 /* Expand the line, replacing tabs with spaces, and control
2908 * characters with their displayed forms. */
Chris Allegretta6f083322009-11-11 06:00:33 +00002909 converted = display_string(fileptr->data, index, COLS, !ISSET(SOFTWRAP));
2910#ifdef DEBUG
2911 if (ISSET(SOFTWRAP) && strlen(converted) >= COLS - 2)
2912 fprintf(stderr, "update_line(): converted(2) line = %s\n", converted);
2913#endif
Chris Allegretta05417a22009-08-17 07:52:10 +00002914
2915 /* Paint the line. */
2916 edit_draw(fileptr, converted, line, index);
2917 free(converted);
2918 extralinesused++;
2919 }
2920 }
2921 return extralinesused;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002922}
2923
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002924/* Return TRUE if we need an update after moving horizontally, and FALSE
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002925 * otherwise. We need one if the mark is on or if pww_save and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002926 * placewewant are on different pages. */
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002927bool need_horizontal_update(size_t pww_save)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002928{
2929 return
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002930#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002931 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002932#endif
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002933 get_page_start(pww_save) !=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002934 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002935}
2936
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002937/* Return TRUE if we need an update after moving vertically, and FALSE
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002938 * otherwise. We need one if the mark is on or if pww_save and
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002939 * placewewant are on different pages. */
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002940bool need_vertical_update(size_t pww_save)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002941{
2942 return
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002943#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002944 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002945#endif
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002946 get_page_start(pww_save) !=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002947 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002948}
2949
Chris Allegretta99c8d402009-11-13 13:48:56 +00002950/* When edittop changes, try and figure out how many lines
Chris Allegretta374216f2010-01-04 19:00:55 +00002951 * we really have to work with (i.e. set maxrows)
Chris Allegretta99c8d402009-11-13 13:48:56 +00002952 */
2953void compute_maxrows(void)
2954{
2955 int n;
2956 filestruct *foo = openfile->edittop;
2957
Chris Allegretta8c1edd12009-11-16 04:28:40 +00002958 if (!ISSET(SOFTWRAP)) {
2959 maxrows = editwinrows;
2960 return;
2961 }
2962
Chris Allegretta99c8d402009-11-13 13:48:56 +00002963 maxrows = 0;
2964 for (n = 0; n < editwinrows && foo; n++) {
Chris Allegrettae2df2c82009-11-24 17:15:53 +00002965 maxrows ++;
2966 n += strlenpt(foo->data) / COLS;
Chris Allegretta99c8d402009-11-13 13:48:56 +00002967 foo = foo->next;
2968 }
2969
Chris Allegretta8c1edd12009-11-16 04:28:40 +00002970 if (n < editwinrows)
2971 maxrows += editwinrows - n;
2972
Chris Allegretta99c8d402009-11-13 13:48:56 +00002973#ifdef DEBUG
2974 fprintf(stderr, "compute_maxrows(): maxrows = %ld\n", maxrows);
2975#endif
Chris Allegretta99c8d402009-11-13 13:48:56 +00002976}
2977
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002978/* Scroll the edit window in the given direction and the given number
2979 * of lines, and draw new lines on the blank lines left after the
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00002980 * scrolling. direction is the direction to scroll, either UP_DIR or
2981 * DOWN_DIR, and nlines is the number of lines to scroll. We change
2982 * edittop, and assume that current and current_x are up to date. We
2983 * also assume that scrollok(edit) is FALSE. */
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002984void edit_scroll(scroll_dir direction, ssize_t nlines)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002985{
Benno Schulenberga8353bd2014-03-17 13:15:50 +00002986 ssize_t i;
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002987 filestruct *foo;
Chris Allegretta139934a2009-08-30 03:50:16 +00002988 bool do_redraw = FALSE;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002989
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002990 /* Don't bother scrolling less than one line. */
2991 if (nlines < 1)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002992 return;
2993
Chris Allegretta5687c3d2009-09-03 02:48:35 +00002994 if (need_vertical_update(0))
Chris Allegretta139934a2009-08-30 03:50:16 +00002995 do_redraw = TRUE;
2996
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002997 /* Part 1: nlines is the number of lines we're going to scroll the
2998 * text of the edit window. */
2999
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003000 /* Move the top line of the edit window up or down (depending on the
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003001 * value of direction) nlines lines, or as many lines as we can if
3002 * there are fewer than nlines lines available. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003003 for (i = nlines; i > 0; i--) {
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00003004 if (direction == UP_DIR) {
David Lawrence Ramseye99223d2005-11-10 04:27:30 +00003005 if (openfile->edittop == openfile->fileage)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003006 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003007 openfile->edittop = openfile->edittop->prev;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003008 } else {
David Lawrence Ramseye99223d2005-11-10 04:27:30 +00003009 if (openfile->edittop == openfile->filebot)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003010 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003011 openfile->edittop = openfile->edittop->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003012 }
Chris Allegretta3b830ee2009-11-27 03:04:59 +00003013 /* Don't over-scroll on long lines */
Benno Schulenbergb1a7fdd2014-03-03 10:02:13 +00003014 if (ISSET(SOFTWRAP) && (direction == UP_DIR)) {
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003015 ssize_t len = strlenpt(openfile->edittop->data) / COLS;
3016 i -= len;
3017 if (len > 0)
3018 do_redraw = TRUE;
3019 }
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003020 }
3021
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00003022 /* Limit nlines to the number of lines we could scroll. */
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00003023 nlines -= i;
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00003024
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00003025 /* Don't bother scrolling zero lines or more than the number of
3026 * lines in the edit window minus one; in both cases, get out, and
David Lawrence Ramsey1072fce2007-09-16 16:53:20 +00003027 * call edit_refresh() beforehand if we need to. */
Chris Allegretta139934a2009-08-30 03:50:16 +00003028 if (nlines == 0 || do_redraw || nlines >= editwinrows) {
David Lawrence Ramsey1072fce2007-09-16 16:53:20 +00003029 if (do_redraw || nlines >= editwinrows)
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003030 edit_refresh_needed = TRUE;
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00003031 return;
3032 }
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003033
3034 /* Scroll the text of the edit window up or down nlines lines,
3035 * depending on the value of direction. */
David Lawrence Ramsey47bb8882005-07-22 22:56:03 +00003036 scrollok(edit, TRUE);
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00003037 wscrl(edit, (direction == UP_DIR) ? -nlines : nlines);
David Lawrence Ramsey47bb8882005-07-22 22:56:03 +00003038 scrollok(edit, FALSE);
3039
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003040 /* Part 2: nlines is the number of lines in the scrolled region of
3041 * the edit window that we need to draw. */
3042
David Lawrence Ramsey68346502005-08-16 03:03:15 +00003043 /* If the top or bottom line of the file is now visible in the edit
3044 * window, we need to draw the entire edit window. */
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00003045 if ((direction == UP_DIR && openfile->edittop ==
3046 openfile->fileage) || (direction == DOWN_DIR &&
3047 openfile->edittop->lineno + editwinrows - 1 >=
3048 openfile->filebot->lineno))
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00003049 nlines = editwinrows;
David Lawrence Ramseya7f488b2005-07-17 02:19:47 +00003050
David Lawrence Ramseya6eb8482006-01-10 07:51:49 +00003051 /* If the scrolled region contains only one line, and the line
3052 * before it is visible in the edit window, we need to draw it too.
3053 * If the scrolled region contains more than one line, and the lines
3054 * before and after the scrolled region are visible in the edit
3055 * window, we need to draw them too. */
3056 nlines += (nlines == 1) ? 1 : 2;
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00003057
David Lawrence Ramseyde0c5eb2005-07-17 22:51:44 +00003058 if (nlines > editwinrows)
3059 nlines = editwinrows;
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003060
3061 /* If we scrolled up, we're on the line before the scrolled
3062 * region. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003063 foo = openfile->edittop;
David Lawrence Ramsey14588912005-07-14 20:37:01 +00003064
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003065 /* If we scrolled down, move down to the line before the scrolled
3066 * region. */
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00003067 if (direction == DOWN_DIR) {
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003068 for (i = editwinrows - nlines; i > 0 && foo != NULL; i--)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003069 foo = foo->next;
3070 }
3071
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003072 /* Draw new lines on any blank lines before or inside the scrolled
3073 * region. If we scrolled down and we're on the top line, or if we
3074 * scrolled up and we're on the bottom line, the line won't be
3075 * blank, so we don't need to draw it unless the mark is on or we're
3076 * not on the first page. */
3077 for (i = nlines; i > 0 && foo != NULL; i--) {
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00003078 if ((i == nlines && direction == DOWN_DIR) || (i == 1 &&
3079 direction == UP_DIR)) {
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003080 if (do_redraw)
3081 update_line(foo, (foo == openfile->current) ?
3082 openfile->current_x : 0);
3083 } else
3084 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003085 openfile->current_x : 0);
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003086 foo = foo->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003087 }
Benno Schulenbergdf7bba32014-02-26 11:38:30 +00003088 compute_maxrows();
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003089}
3090
3091/* Update any lines between old_current and current that need to be
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00003092 * updated. Use this if we've moved without changing any text. */
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00003093void edit_redraw(filestruct *old_current, size_t pww_save)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003094{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003095 bool do_redraw = need_vertical_update(0) ||
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00003096 need_vertical_update(pww_save);
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00003097 filestruct *foo = NULL;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003098
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003099 /* If either old_current or current is offscreen, scroll the edit
3100 * window until it's onscreen and get out. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003101 if (old_current->lineno < openfile->edittop->lineno ||
3102 old_current->lineno >= openfile->edittop->lineno +
Chris Allegretta99c8d402009-11-13 13:48:56 +00003103 maxrows || openfile->current->lineno <
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003104 openfile->edittop->lineno || openfile->current->lineno >=
Chris Allegretta99c8d402009-11-13 13:48:56 +00003105 openfile->edittop->lineno + maxrows) {
Chris Allegretta139934a2009-08-30 03:50:16 +00003106
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003107#ifdef DEBUG
3108 fprintf(stderr, "edit_redraw(): line %lu was offscreen, oldcurrent = %lu edittop = %lu", openfile->current->lineno,
3109 old_current->lineno, openfile->edittop->lineno);
3110#endif
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003111
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003112#ifndef NANO_TINY
3113 /* If the mark is on, update all the lines between old_current
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003114 * and either the old first line or old last line (depending on
3115 * whether we've scrolled up or down) of the edit window. */
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003116 if (openfile->mark_set) {
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003117 ssize_t old_lineno;
Chris Allegretta4cc24622013-01-03 04:23:10 +00003118 filestruct *old_edittop = openfile->edittop;
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003119
3120 if (old_edittop->lineno < openfile->edittop->lineno)
3121 old_lineno = old_edittop->lineno;
3122 else
Chris Allegretta99c8d402009-11-13 13:48:56 +00003123 old_lineno = (old_edittop->lineno + maxrows <=
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003124 openfile->filebot->lineno) ?
3125 old_edittop->lineno + editwinrows :
3126 openfile->filebot->lineno;
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003127
3128 foo = old_current;
3129
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003130 while (foo->lineno != old_lineno) {
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003131 update_line(foo, 0);
3132
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003133 foo = (foo->lineno > old_lineno) ? foo->prev :
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003134 foo->next;
3135 }
3136 }
3137#endif /* !NANO_TINY */
3138
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003139 /* Put edittop in range of current, get the difference in lines
3140 * between the original edittop and the current edittop, and
3141 * then restore the original edittop. */
Chris Allegretta374216f2010-01-04 19:00:55 +00003142 edit_update(CENTER);
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003143
David Lawrence Ramseyb0063672006-07-06 18:29:37 +00003144 /* Update old_current if we're not on the same page as
3145 * before. */
David Lawrence Ramseya6eb8482006-01-10 07:51:49 +00003146 if (do_redraw)
3147 update_line(old_current, 0);
3148
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003149#ifndef NANO_TINY
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003150 /* If the mark is on, update all the lines between the old first
3151 * line or old last line of the edit window (depending on
3152 * whether we've scrolled up or down) and current. */
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003153 if (openfile->mark_set) {
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003154 while (foo->lineno != openfile->current->lineno) {
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003155 update_line(foo, 0);
3156
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003157 foo = (foo->lineno > openfile->current->lineno) ?
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003158 foo->prev : foo->next;
3159 }
3160 }
3161#endif /* !NANO_TINY */
3162
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003163 return;
3164 }
3165
David Lawrence Ramseyb0063672006-07-06 18:29:37 +00003166 /* Update old_current and current if we're not on the same page as
3167 * before. If the mark is on, update all the lines between
3168 * old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003169 foo = old_current;
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003170
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003171 while (foo != openfile->current) {
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003172 if (do_redraw)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003173 update_line(foo, 0);
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003174
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00003175#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003176 if (!openfile->mark_set)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003177#endif
3178 break;
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003179
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00003180#ifndef NANO_TINY
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003181 foo = (foo->lineno > openfile->current->lineno) ? foo->prev :
3182 foo->next;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003183#endif
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003184 }
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003185
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003186 if (do_redraw)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003187 update_line(openfile->current, openfile->current_x);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003188}
3189
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00003190/* Refresh the screen without changing the position of lines. Use this
3191 * if we've moved and changed text. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003192void edit_refresh(void)
3193{
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00003194 filestruct *foo;
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003195 int nlines;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003196
Chris Allegretta99c8d402009-11-13 13:48:56 +00003197 /* Figure out what maxrows should really be */
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003198 compute_maxrows();
Chris Allegretta99c8d402009-11-13 13:48:56 +00003199
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003200 if (openfile->current->lineno < openfile->edittop->lineno ||
3201 openfile->current->lineno >= openfile->edittop->lineno +
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003202 maxrows) {
3203
3204#ifdef DEBUG
3205 fprintf(stderr, "edit_refresh(): line = %d, edittop %d + maxrows %d\n", openfile->current->lineno, openfile->edittop->lineno, maxrows);
3206#endif
3207
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003208 /* Put the top line of the edit window in range of the current
3209 * line. */
Chris Allegretta374216f2010-01-04 19:00:55 +00003210 edit_update(CENTER);
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003211 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003212
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003213 foo = openfile->edittop;
3214
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003215#ifdef DEBUG
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003216 fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", (long)openfile->edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003217#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003218
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003219 for (nlines = 0; nlines < editwinrows && foo != NULL; nlines++) {
Chris Allegretta05417a22009-08-17 07:52:10 +00003220 nlines += update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003221 openfile->current_x : 0);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003222 foo = foo->next;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003223 }
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003224
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003225 for (; nlines < editwinrows; nlines++)
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003226 blank_line(edit, nlines, 0, COLS);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003227
3228 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00003229 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003230}
3231
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003232/* Move edittop to put it in range of current, keeping current in the
3233 * same place. location determines how we move it: if it's CENTER, we
3234 * center current, and if it's NONE, we put current current_y lines
3235 * below edittop. */
David Lawrence Ramseybf0e47d2005-08-01 18:27:10 +00003236void edit_update(update_type location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003237{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003238 filestruct *foo = openfile->current;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003239 int goal;
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003240
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003241 /* If location is CENTER, we move edittop up (editwinrows / 2)
3242 * lines. This puts current at the center of the screen. If
3243 * location is NONE, we move edittop up current_y lines if current_y
3244 * is in range of the screen, 0 lines if current_y is less than 0,
3245 * or (editwinrows - 1) lines if current_y is greater than
3246 * (editwinrows - 1). This puts current at the same place on the
3247 * screen as before, or at the top or bottom of the screen if
3248 * edittop is beyond either. */
3249 if (location == CENTER)
Chris Allegretta374216f2010-01-04 19:00:55 +00003250 goal = editwinrows / 2;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003251 else {
3252 goal = openfile->current_y;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003253
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003254 /* Limit goal to (editwinrows - 1) lines maximum. */
Chris Allegretta374216f2010-01-04 19:00:55 +00003255 if (goal > editwinrows - 1)
3256 goal = editwinrows - 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003257 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003258
Chris Allegretta35afab52009-09-13 04:50:44 +00003259 for (; goal > 0 && foo->prev != NULL; goal--) {
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003260 foo = foo->prev;
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003261 if (ISSET(SOFTWRAP) && foo)
3262 goal -= strlenpt(foo->data) / COLS;
Chris Allegretta35afab52009-09-13 04:50:44 +00003263 }
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003264 openfile->edittop = foo;
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003265#ifdef DEBUG
3266 fprintf(stderr, "edit_udpate(), setting edittop to lineno %d\n", openfile->edittop->lineno);
3267#endif
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003268 compute_maxrows();
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003269 edit_refresh_needed = TRUE;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003270}
3271
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003272/* Unconditionally redraw the entire screen. */
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003273void total_redraw(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003274{
David Lawrence Ramseyf78bc852007-12-18 15:55:48 +00003275#ifdef USE_SLANG
3276 /* Slang curses emulation brain damage, part 4: Slang doesn't define
3277 * curscr. */
3278 SLsmg_touch_screen();
3279 SLsmg_refresh();
3280#else
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00003281 wrefresh(curscr);
David Lawrence Ramseyf78bc852007-12-18 15:55:48 +00003282#endif
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003283}
3284
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003285/* Unconditionally redraw the entire screen, and then refresh it using
3286 * the current file. */
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003287void total_refresh(void)
3288{
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003289 total_redraw();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003290 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003291 edit_refresh();
Chris Allegretta79a33bb2008-03-05 07:34:01 +00003292 bottombars(currmenu);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003293}
3294
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003295/* Display the main shortcut list on the last two rows of the bottom
3296 * portion of the window. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003297void display_main_list(void)
3298{
Chris Allegretta5575bfa2014-02-24 10:18:15 +00003299#ifdef ENABLE_COLOR
3300 if (openfile->syntax && openfile->syntax->linter)
3301 set_lint_shortcuts();
3302 else
3303 set_spell_shortcuts();
3304#endif
3305
Chris Allegretta79a33bb2008-03-05 07:34:01 +00003306 bottombars(MMAIN);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003307}
3308
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003309/* If constant is TRUE, we display the current cursor position only if
3310 * disable_cursorpos is FALSE. Otherwise, we display it
3311 * unconditionally and set disable_cursorpos to FALSE. If constant is
3312 * TRUE and disable_cursorpos is TRUE, we also set disable_cursorpos to
3313 * FALSE, so that we leave the current statusbar alone this time, and
3314 * display the current cursor position next time. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003315void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003316{
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003317 filestruct *f;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003318 char c;
David Lawrence Ramsey5745c0a2005-07-31 20:20:37 +00003319 size_t i, cur_xpt = xplustabs() + 1;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003320 size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003321 int linepct, colpct, charpct;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003322
David Lawrence Ramsey4ab80152005-07-31 18:51:51 +00003323 assert(openfile->fileage != NULL && openfile->current != NULL);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003324
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003325 f = openfile->current->next;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003326 c = openfile->current->data[openfile->current_x];
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003327
3328 openfile->current->next = NULL;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003329 openfile->current->data[openfile->current_x] = '\0';
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003330
3331 i = get_totsize(openfile->fileage, openfile->current);
3332
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003333 openfile->current->data[openfile->current_x] = c;
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003334 openfile->current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003335
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003336 if (constant && disable_cursorpos) {
3337 disable_cursorpos = FALSE;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003338 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003339 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003340
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00003341 /* Display the current cursor position on the statusbar, and set
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003342 * disable_cursorpos to FALSE. */
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003343 linepct = 100 * openfile->current->lineno /
3344 openfile->filebot->lineno;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003345 colpct = 100 * cur_xpt / cur_lenpt;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003346 charpct = (openfile->totsize == 0) ? 0 : 100 * i /
3347 openfile->totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003348
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003349 statusbar(
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003350 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003351 (long)openfile->current->lineno,
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003352 (long)openfile->filebot->lineno, linepct,
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003353 (unsigned long)cur_xpt, (unsigned long)cur_lenpt, colpct,
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003354 (unsigned long)i, (unsigned long)openfile->totsize, charpct);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003355
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003356 disable_cursorpos = FALSE;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003357}
3358
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003359/* Unconditionally display the current cursor position. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003360void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003361{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003362 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003363}
3364
Chris Allegretta0dc26dc2009-01-24 22:40:41 +00003365void enable_nodelay(void)
3366{
3367 nodelay_mode = TRUE;
3368 nodelay(edit, TRUE);
3369}
3370
3371void disable_nodelay(void)
3372{
3373 nodelay_mode = FALSE;
3374 nodelay(edit, FALSE);
3375}
3376
3377
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003378/* Highlight the current word being replaced or spell checked. We
3379 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003380void do_replace_highlight(bool highlight, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003381{
David Lawrence Ramsey6168cb72005-06-30 03:53:28 +00003382 size_t y = xplustabs(), word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003383
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003384 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003385 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003386 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003387
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003388 assert(y > 0);
3389
3390 if (word_len > y)
3391 y--;
3392
Chris Allegrettafb62f732000-12-05 11:36:41 +00003393 reset_cursor();
David Lawrence Ramsey98958e82007-12-04 16:38:47 +00003394 wnoutrefresh(edit);
Chris Allegretta598106e2002-01-19 01:59:37 +00003395
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003396 if (highlight)
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00003397 wattron(edit, reverse_attr);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003398
David Lawrence Ramsey21b946e2006-11-10 20:13:38 +00003399 /* This is so we can show zero-length matches. */
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003400 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00003401 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003402 else
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003403 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003404
3405 if (word_len > y)
3406 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003407
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003408 if (highlight)
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00003409 wattroff(edit, reverse_attr);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003410}
3411
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003412#ifdef NANO_EXTRA
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003413#define CREDIT_LEN 57
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003414#define XLCREDIT_LEN 8
3415
David Lawrence Ramsey8ad58bc2005-08-16 03:02:46 +00003416/* Easter egg: Display credits. Assume nodelay(edit) and scrollok(edit)
3417 * are FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003418void do_credits(void)
3419{
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003420 bool old_more_space = ISSET(MORE_SPACE);
3421 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003422 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003423 const char *credits[CREDIT_LEN] = {
3424 NULL, /* "The nano text editor" */
3425 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003426 VERSION,
3427 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003428 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003429 "Chris Allegretta",
3430 "Jordi Mallach",
3431 "Adam Rogoyski",
3432 "Rob Siemborski",
3433 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003434 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003435 "David Benbennick",
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003436 "Mike Frysinger",
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003437 "Benno Schulenberg",
Chris Allegretta598106e2002-01-19 01:59:37 +00003438 "Ken Tyler",
3439 "Sven Guckes",
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003440 NULL, /* credits[16], handled below. */
Chris Allegretta598106e2002-01-19 01:59:37 +00003441 "Pauli Virtanen",
3442 "Daniele Medri",
3443 "Clement Laforet",
3444 "Tedi Heriyanto",
3445 "Bill Soudan",
3446 "Christian Weisgerber",
3447 "Erik Andersen",
3448 "Big Gaute",
3449 "Joshua Jensen",
3450 "Ryan Krebs",
3451 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003452 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003453 NULL, /* "Special thanks to:" */
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003454 "Monique, Brielle & Joseph",
Chris Allegretta598106e2002-01-19 01:59:37 +00003455 "Plattsburgh State University",
3456 "Benet Laboratories",
3457 "Amy Allegretta",
3458 "Linda Young",
3459 "Jeremy Robichaud",
3460 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003461 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003462 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003463 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003464 "Thomas Dickey",
3465 "Pavel Curtis",
3466 "Zeyd Ben-Halim",
3467 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003468 NULL, /* "and anyone else we forgot..." */
3469 NULL, /* "Thank you for using nano!" */
3470 "",
3471 "",
3472 "",
3473 "",
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003474 "(C) 1999 - 2014",
David Lawrence Ramseyd8a1d372007-10-11 05:01:32 +00003475 "Free Software Foundation, Inc.",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003476 "",
3477 "",
3478 "",
3479 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003480 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003481 };
3482
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003483 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003484 N_("The nano text editor"),
3485 N_("version"),
3486 N_("Brought to you by:"),
3487 N_("Special thanks to:"),
3488 N_("The Free Software Foundation"),
3489 N_("For ncurses:"),
3490 N_("and anyone else we forgot..."),
3491 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003492 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003493
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003494 /* credits[15]: Make sure this name is displayed properly, since we
David Lawrence Ramsey62d616b2005-07-06 19:20:32 +00003495 * can't dynamically assign it above, using Unicode 00F6 (Latin
3496 * Small Letter O with Diaresis) if applicable. */
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003497 credits[16] =
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00003498#ifdef ENABLE_UTF8
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00003499 using_utf8() ? "Florian K\xC3\xB6nig" :
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003500#endif
3501 "Florian K\xF6nig";
3502
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003503 if (!old_more_space || !old_no_help) {
3504 SET(MORE_SPACE);
3505 SET(NO_HELP);
3506 window_init();
3507 }
3508
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003509 curs_set(0);
3510 nodelay(edit, TRUE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003511
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003512 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003513 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003514 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003515 blank_statusbar();
3516 blank_bottombars();
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003517
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003518 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003519 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003520 wrefresh(bottomwin);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003521 napms(700);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003522
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003523 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003524 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003525 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003526
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003527 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003528 const char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003529 size_t start_x;
3530
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003531 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003532 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003533
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003534 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003535 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003536 } else
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003537 what = credits[crpos];
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003538
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003539 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003540 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
3541 start_x, what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003542 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003543
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003544 wrefresh(edit);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003545
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003546 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003547 break;
3548 napms(700);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003549
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003550 scrollok(edit, TRUE);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003551 wscrl(edit, 1);
3552 scrollok(edit, FALSE);
3553 wrefresh(edit);
3554
3555 if ((kbinput = wgetch(edit)) != ERR)
3556 break;
3557 napms(700);
3558
3559 scrollok(edit, TRUE);
3560 wscrl(edit, 1);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003561 scrollok(edit, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003562 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003563 }
3564
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003565 if (kbinput != ERR)
3566 ungetch(kbinput);
3567
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003568 if (!old_more_space || !old_no_help) {
3569 UNSET(MORE_SPACE);
3570 UNSET(NO_HELP);
3571 window_init();
3572 }
3573
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003574 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003575 nodelay(edit, FALSE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003576
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003577 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003578}
David Lawrence Ramsey172aa932006-04-18 15:58:50 +00003579#endif /* NANO_EXTRA */