blob: 1c5dc3afc6e7ec7309d488f5aa2544ddfcd0c6c1 [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, *
Benno Schulenberg7a9f4a42014-04-30 20:18:26 +00006 * 2008, 2009, 2010, 2011, 2013, 2014 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
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000115#ifndef NANO_TINY
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000116 allow_pending_sigwinch(TRUE);
117#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000118
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +0000119 /* Just before reading in the first character, display any pending
120 * screen updates. */
121 doupdate();
122
Benno Schulenbergf876ee12014-04-15 11:25:29 +0000123 /* Read in the first character using whatever mode we're in. */
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
Benno Schulenbergf876ee12014-04-15 11:25:29 +0000177 /* Switch back to waiting mode for input. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000178 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
Benno Schulenbergf876ee12014-04-15 11:25:29 +0000307 * off. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000308int 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
Benno Schulenbergf876ee12014-04-15 11:25:29 +0000327 * a function key. */
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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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. */
Benno Schulenberg25e58962014-04-23 19:33:03 +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':
Benno Schulenberg25e58962014-04-23 19:33:03 +00001223 return sc_seq_or(do_up_void, 0);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001224 case 'b':
Benno Schulenberg25e58962014-04-23 19:33:03 +00001225 return sc_seq_or(do_down_void, 0);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001226 case 'c':
Benno Schulenberg25e58962014-04-23 19:33:03 +00001227 return sc_seq_or(do_right, 0);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001228 case 'd':
Benno Schulenberg25e58962014-04-23 19:33:03 +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
Benno Schulenbergf876ee12014-04-15 11:25:29 +00001304 * was two and the second was five, and may be any decimal
1305 * value otherwise. Put it in the 1's position of the byte
1306 * sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001307 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1308 '6' <= kbinput && kbinput <= '9')) {
David Lawrence Ramsey28889642006-05-30 20:51:15 +00001309 byte += kbinput - '0';
Benno Schulenbergf876ee12014-04-15 11:25:29 +00001310 /* The byte sequence is complete. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001311 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001312 } else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001313 /* This isn't the third digit of a byte sequence.
1314 * Return this character as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001315 retval = kbinput;
1316 break;
1317 default:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001318 /* If there are more than three digits, return this
1319 * character as the result. (Maybe we should produce an
1320 * error instead?) */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001321 retval = kbinput;
1322 break;
1323 }
1324
1325 /* If we have a result, reset the byte digit counter and the byte
1326 * sequence holder. */
1327 if (retval != ERR) {
1328 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001329 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001330 }
1331
1332#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001333 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 +00001334#endif
1335
1336 return retval;
1337}
1338
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001339#ifdef ENABLE_UTF8
David Lawrence Ramsey7f1b1192006-05-28 17:30:28 +00001340/* If the character in kbinput is a valid hexadecimal digit, multiply it
1341 * by factor and add the result to uni. */
1342long add_unicode_digit(int kbinput, long factor, long *uni)
1343{
1344 long retval = ERR;
1345
1346 if ('0' <= kbinput && kbinput <= '9')
1347 *uni += (kbinput - '0') * factor;
1348 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
1349 *uni += (tolower(kbinput) - 'a' + 10) * factor;
1350 else
1351 /* If this character isn't a valid hexadecimal value, save it as
1352 * the result. */
1353 retval = kbinput;
1354
1355 return retval;
1356}
1357
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001358/* Translate a Unicode sequence: turn a six-digit hexadecimal number
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001359 * (from 000000 to 10FFFF, case-insensitive) into its corresponding
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001360 * multibyte value. */
David Lawrence Ramseyfc0f8f82006-05-10 13:41:53 +00001361long get_unicode_kbinput(int kbinput)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001362{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001363 static int uni_digits = 0;
1364 static long uni = 0;
1365 long retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001366
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001367 /* Increment the Unicode digit counter. */
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001368 uni_digits++;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001369
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001370 switch (uni_digits) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001371 case 1:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001372 /* First digit: This must be zero or one. Put it in the
1373 * 0x100000's position of the Unicode sequence holder. */
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001374 if ('0' <= kbinput && kbinput <= '1')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001375 uni = (kbinput - '0') * 0x100000;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001376 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001377 /* This isn't the first digit of a Unicode sequence.
1378 * Return this character as the result. */
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001379 retval = kbinput;
1380 break;
1381 case 2:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001382 /* Second digit: This must be zero if the first was one, and
1383 * may be any hexadecimal value if the first was zero. Put
1384 * it in the 0x10000's position of the Unicode sequence
1385 * holder. */
1386 if (uni == 0 || '0' == kbinput)
1387 retval = add_unicode_digit(kbinput, 0x10000, &uni);
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001388 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001389 /* This isn't the second digit of a Unicode sequence.
1390 * Return this character as the result. */
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001391 retval = kbinput;
1392 break;
1393 case 3:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001394 /* Third digit: This may be any hexadecimal value. Put it
1395 * in the 0x1000's position of the Unicode sequence
1396 * holder. */
1397 retval = add_unicode_digit(kbinput, 0x1000, &uni);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001398 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001399 case 4:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001400 /* Fourth digit: This may be any hexadecimal value. Put it
1401 * in the 0x100's position of the Unicode sequence
1402 * holder. */
1403 retval = add_unicode_digit(kbinput, 0x100, &uni);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001404 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001405 case 5:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001406 /* Fifth digit: This may be any hexadecimal value. Put it
1407 * in the 0x10's position of the Unicode sequence holder. */
1408 retval = add_unicode_digit(kbinput, 0x10, &uni);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001409 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001410 case 6:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001411 /* Sixth digit: This may be any hexadecimal value. Put it
1412 * in the 0x1's position of the Unicode sequence holder. */
1413 retval = add_unicode_digit(kbinput, 0x1, &uni);
1414 /* If this character is a valid hexadecimal value, then the
1415 * Unicode sequence is complete. */
1416 if (retval == ERR)
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001417 retval = uni;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001418 break;
1419 default:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001420 /* If there are more than six digits, return this character
1421 * as the result. (Maybe we should produce an error
1422 * instead?) */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001423 retval = kbinput;
1424 break;
1425 }
1426
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001427 /* If we have a result, reset the Unicode digit counter and the
1428 * Unicode sequence holder. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001429 if (retval != ERR) {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001430 uni_digits = 0;
1431 uni = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001432 }
1433
1434#ifdef DEBUG
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001435 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 +00001436#endif
1437
1438 return retval;
1439}
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001440#endif /* ENABLE_UTF8 */
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001441
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001442/* Translate a control character sequence: turn an ASCII non-control
1443 * character into its corresponding control character. */
1444int get_control_kbinput(int kbinput)
1445{
1446 int retval;
1447
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001448 /* Ctrl-Space (Ctrl-2, Ctrl-@, Ctrl-`) */
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001449 if (kbinput == ' ' || kbinput == '2')
1450 retval = NANO_CONTROL_SPACE;
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001451 /* Ctrl-/ (Ctrl-7, Ctrl-_) */
1452 else if (kbinput == '/')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001453 retval = NANO_CONTROL_7;
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001454 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-/, Ctrl-_) */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001455 else if ('3' <= kbinput && kbinput <= '7')
1456 retval = kbinput - 24;
1457 /* Ctrl-8 (Ctrl-?) */
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001458 else if (kbinput == '8' || kbinput == '?')
1459 retval = NANO_CONTROL_8;
David Lawrence Ramsey51cb7fd2006-05-20 17:19:09 +00001460 /* Ctrl-@ (Ctrl-Space, Ctrl-2, Ctrl-`) to Ctrl-_ (Ctrl-/, Ctrl-7) */
1461 else if ('@' <= kbinput && kbinput <= '_')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001462 retval = kbinput - '@';
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001463 /* Ctrl-` (Ctrl-2, Ctrl-Space, Ctrl-@) to Ctrl-~ (Ctrl-6, Ctrl-^) */
1464 else if ('`' <= kbinput && kbinput <= '~')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001465 retval = kbinput - '`';
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001466 else
1467 retval = kbinput;
1468
1469#ifdef DEBUG
1470 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1471#endif
1472
1473 return retval;
1474}
1475
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +00001476/* Put the output-formatted characters in output back into the keystroke
1477 * buffer, so that they can be parsed and displayed as output again. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001478void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001479{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001480 int *input;
1481 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001482
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001483 if (output_len == 0)
1484 return;
1485
1486 input = (int *)nmalloc(output_len * sizeof(int));
David Lawrence Ramseybd539802006-12-02 23:39:16 +00001487
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001488 for (i = 0; i < output_len; i++)
1489 input[i] = (int)output[i];
David Lawrence Ramseybd539802006-12-02 23:39:16 +00001490
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001491 unget_input(input, output_len);
David Lawrence Ramseybd539802006-12-02 23:39:16 +00001492
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001493 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001494}
1495
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001496/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001497 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1498int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1499{
1500 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001501
1502 /* Turn off flow control characters if necessary so that we can type
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001503 * them in verbatim, and turn the keypad off if necessary so that we
1504 * don't get extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001505 if (ISSET(PRESERVE))
1506 disable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001507 if (!ISSET(REBIND_KEYPAD))
1508 keypad(win, FALSE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001509
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001510 /* Read in a stream of characters and interpret it if possible. */
1511 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001512
1513 /* Turn flow control characters back on if necessary and turn the
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001514 * keypad back on if necessary now that we're done. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001515 if (ISSET(PRESERVE))
1516 enable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001517 if (!ISSET(REBIND_KEYPAD))
1518 keypad(win, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001519
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001520 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001521}
1522
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001523/* Read in a stream of all available characters, and return the length
1524 * of the string in kbinput_len. Translate the first few characters of
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001525 * the input into the corresponding multibyte value if possible. After
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00001526 * that, leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001527int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001528{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001529 int *kbinput, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001530
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001531 /* Read in the first keystroke. */
1532 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001533
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001534#ifdef ENABLE_UTF8
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001535 if (using_utf8()) {
1536 /* Check whether the first keystroke is a valid hexadecimal
1537 * digit. */
David Lawrence Ramseya5b1ca22006-05-28 17:09:49 +00001538 long uni = get_unicode_kbinput(*kbinput);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001539
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001540 /* If the first keystroke isn't a valid hexadecimal digit, put
1541 * back the first keystroke. */
1542 if (uni != ERR)
1543 unget_input(kbinput, 1);
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001544
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001545 /* Otherwise, read in keystrokes until we have a complete
1546 * Unicode sequence, and put back the corresponding Unicode
1547 * value. */
1548 else {
1549 char *uni_mb;
1550 int uni_mb_len, *seq, i;
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001551
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001552 if (win == edit)
1553 /* TRANSLATORS: This is displayed during the input of a
1554 * six-digit hexadecimal Unicode character code. */
1555 statusbar(_("Unicode Input"));
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001556
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001557 while (uni == ERR) {
1558 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001559
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001560 uni = get_unicode_kbinput(*kbinput);
1561 }
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001562
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001563 /* Put back the multibyte equivalent of the Unicode
1564 * value. */
1565 uni_mb = make_mbchar(uni, &uni_mb_len);
1566
1567 seq = (int *)nmalloc(uni_mb_len * sizeof(int));
1568
1569 for (i = 0; i < uni_mb_len; i++)
1570 seq[i] = (unsigned char)uni_mb[i];
1571
1572 unget_input(seq, uni_mb_len);
1573
1574 free(seq);
1575 free(uni_mb);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001576 }
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001577 } else
David Lawrence Ramseya5b1ca22006-05-28 17:09:49 +00001578#endif /* ENABLE_UTF8 */
1579
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001580 /* Put back the first keystroke. */
1581 unget_input(kbinput, 1);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001582
David Lawrence Ramseyad36bdc2006-12-02 17:22:21 +00001583 free(kbinput);
1584
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001585 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001586 * result. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00001587 *kbinput_len = get_key_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001588 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001589
1590 return retval;
1591}
1592
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001593#ifndef DISABLE_MOUSE
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001594/* Handle any mouse event that may have occurred. We currently handle
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001595 * releases/clicks of the first mouse button. If allow_shortcuts is
1596 * TRUE, releasing/clicking on a visible shortcut will put back the
1597 * keystroke associated with that shortcut. If NCURSES_MOUSE_VERSION is
1598 * at least 2, we also currently handle presses of the fourth mouse
1599 * button (upward rolls of the mouse wheel) by putting back the
1600 * keystrokes to move up, and presses of the fifth mouse button
1601 * (downward rolls of the mouse wheel) by putting back the keystrokes to
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001602 * move down. We also store the coordinates of a mouse event that needs
1603 * to be handled in mouse_x and mouse_y, relative to the entire screen.
1604 * Return -1 on error, 0 if the mouse event needs to be handled, 1 if
1605 * it's been handled by putting back keystrokes that need to be handled.
1606 * or 2 if it's been ignored. Assume that KEY_MOUSE has already been
1607 * read in. */
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001608int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001609{
1610 MEVENT mevent;
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001611 bool in_bottomwin;
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001612 subnfunc *f;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001613
1614 *mouse_x = -1;
1615 *mouse_y = -1;
1616
1617 /* First, get the actual mouse event. */
1618 if (getmouse(&mevent) == ERR)
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001619 return -1;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001620
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001621 /* Save the screen coordinates where the mouse event took place. */
1622 *mouse_x = mevent.x;
1623 *mouse_y = mevent.y;
David Lawrence Ramsey98e4d4f2006-06-28 21:54:55 +00001624
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001625 in_bottomwin = wenclose(bottomwin, *mouse_y, *mouse_x);
1626
David Lawrence Ramsey5fcf8bf2007-06-28 18:31:13 +00001627 /* Handle releases/clicks of the first mouse button. */
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001628 if (mevent.bstate & (BUTTON1_RELEASED | BUTTON1_CLICKED)) {
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001629 /* If we're allowing shortcuts, the current shortcut list is
1630 * being displayed on the last two lines of the screen, and the
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001631 * first mouse button was released on/clicked inside it, we need
1632 * to figure out which shortcut was released on/clicked and put
1633 * back the equivalent keystroke(s) for it. */
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001634 if (allow_shortcuts && !ISSET(NO_HELP) && in_bottomwin) {
David Lawrence Ramseybc653132007-05-22 17:20:28 +00001635 int i;
1636 /* The width of all the shortcuts, except for the last
1637 * two, in the shortcut list in bottomwin. */
1638 int j;
1639 /* The y-coordinate relative to the beginning of the
1640 * shortcut list in bottomwin. */
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001641 size_t currslen;
1642 /* The number of shortcuts in the current shortcut
1643 * list. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001644
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001645 /* Translate the mouse event coordinates so that they're
1646 * relative to bottomwin. */
1647 wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE);
1648
1649 /* Handle releases/clicks of the first mouse button on the
1650 * statusbar elsewhere. */
1651 if (*mouse_y == 0) {
1652 /* Restore the untranslated mouse event coordinates, so
1653 * that they're relative to the entire screen again. */
1654 *mouse_x = mevent.x;
1655 *mouse_y = mevent.y;
1656
1657 return 0;
1658 }
David Lawrence Ramseybc653132007-05-22 17:20:28 +00001659
1660 /* Calculate the y-coordinate relative to the beginning of
1661 * the shortcut list in bottomwin. */
1662 j = *mouse_y - 1;
1663
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001664 /* Get the shortcut lists' length. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001665 if (currmenu == MMAIN)
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001666 currslen = MAIN_VISIBLE;
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001667 else {
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001668 currslen = length_of_list(currmenu);
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001669
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001670 /* We don't show any more shortcuts than the main list
1671 * does. */
1672 if (currslen > MAIN_VISIBLE)
1673 currslen = MAIN_VISIBLE;
1674 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001675
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001676 /* Calculate the width of all of the shortcuts in the list
1677 * except for the last two, which are longer by (COLS % i)
1678 * columns so as to not waste space. */
1679 if (currslen < 2)
1680 i = COLS / (MAIN_VISIBLE / 2);
1681 else
1682 i = COLS / ((currslen / 2) + (currslen % 2));
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001683
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001684 /* Calculate the x-coordinate relative to the beginning of
1685 * the shortcut list in bottomwin, and add it to j. j
1686 * should now be the index in the shortcut list of the
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001687 * shortcut we released/clicked on. */
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001688 j = (*mouse_x / i) * 2 + j;
1689
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001690 /* Adjust j if we released on the last two shortcuts. */
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001691 if ((j >= currslen) && (*mouse_x % i < COLS % i))
1692 j -= 2;
Benno Schulenberg0d843012014-04-16 08:24:32 +00001693#ifdef DEBUG
1694 fprintf(stderr, "Calculated %i as index in shortcut list, currmenu = %x.\n", j, currmenu);
1695#endif
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
Benno Schulenberg0d843012014-04-16 08:24:32 +00001701 /* Go through the list of functions to determine which
1702 * shortcut in the current menu we released/clicked on. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001703 f = allfuncs;
David Lawrence Ramseybc653132007-05-22 17:20:28 +00001704
Benno Schulenberg0d843012014-04-16 08:24:32 +00001705 while (TRUE) {
1706 while ((f->menus & currmenu) == 0
Chris Allegretta1d778232008-08-30 21:00:00 +00001707#ifndef DISABLE_HELP
Benno Schulenberg0d843012014-04-16 08:24:32 +00001708 || strlen(f->help) == 0
Chris Allegretta1d778232008-08-30 21:00:00 +00001709#endif
Benno Schulenberg0d843012014-04-16 08:24:32 +00001710 )
1711 f = f->next;
1712 if (j == 0)
1713 break;
1714 f = f->next;
1715 j -= 1;
Chris Allegrettac0b78722008-03-11 04:52:57 +00001716 }
Benno Schulenberg0d843012014-04-16 08:24:32 +00001717#ifdef DEBUG
Benno Schulenberg27a52a82014-04-21 13:07:18 +00001718 fprintf(stderr, "Stopped on func %ld present in menus %x\n", (long)f->scfunc, f->menus);
Benno Schulenberg0d843012014-04-16 08:24:32 +00001719#endif
Chris Allegrettac0b78722008-03-11 04:52:57 +00001720
Benno Schulenberg0d843012014-04-16 08:24:32 +00001721 /* And put the corresponding key into the keyboard buffer. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001722 if (f != NULL) {
Chris Allegrettaa1171632009-01-19 19:10:39 +00001723 const sc *s = first_sc_for(currmenu, f->scfunc);
Chris Allegrettac0b78722008-03-11 04:52:57 +00001724 if (s != NULL)
1725 unget_kbinput(s->seq, s->type == META, FALSE);
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001726 }
1727 } else
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001728 /* Handle releases/clicks of the first mouse button that
1729 * aren't on the current shortcut list elsewhere. */
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001730 return 0;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001731 }
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001732#if NCURSES_MOUSE_VERSION >= 2
1733 /* Handle presses of the fourth mouse button (upward rolls of the
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001734 * mouse wheel) and presses of the fifth mouse button (downward
1735 * rolls of the mouse wheel) . */
1736 else if (mevent.bstate & (BUTTON4_PRESSED | BUTTON5_PRESSED)) {
David Lawrence Ramseydef60912007-12-08 16:59:13 +00001737 bool in_edit = wenclose(edit, *mouse_y, *mouse_x);
David Lawrence Ramseybc653132007-05-22 17:20:28 +00001738
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001739 if (in_bottomwin)
1740 /* Translate the mouse event coordinates so that they're
1741 * relative to bottomwin. */
1742 wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE);
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001743
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001744 if (in_edit || (in_bottomwin && *mouse_y == 0)) {
David Lawrence Ramseydef60912007-12-08 16:59:13 +00001745 int i;
1746
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001747 /* One upward roll of the mouse wheel is equivalent to
1748 * moving up three lines, and one downward roll of the mouse
1749 * wheel is equivalent to moving down three lines. */
1750 for (i = 0; i < 3; i++)
1751 unget_kbinput((mevent.bstate & BUTTON4_PRESSED) ?
Benno Schulenbergc4520d52014-02-22 19:36:35 +00001752 sc_seq_or(do_up_void, 0) : sc_seq_or(do_down_void, 0),
1753 FALSE, FALSE);
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001754
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001755 return 1;
1756 } else
1757 /* Ignore presses of the fourth mouse button and presses of
1758 * the fifth mouse buttons that aren't on the edit window or
1759 * the statusbar. */
1760 return 2;
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001761 }
1762#endif
David Lawrence Ramseyc8bde572007-06-28 16:38:00 +00001763
1764 /* Ignore all other mouse events. */
1765 return 2;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001766}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001767#endif /* !DISABLE_MOUSE */
1768
Benno Schulenberg7828a802014-04-14 09:22:29 +00001769/* Return the shortcut that corresponds to the values of kbinput (the
1770 * key itself) and meta_key (whether the key is a meta sequence). The
1771 * returned shortcut will be the first in the list that corresponds to
1772 * the given sequence. */
1773const sc *get_shortcut(int menu, int *kbinput, bool *meta_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001774{
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001775 sc *s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001776
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001777#ifdef DEBUG
Benno Schulenberg0d843012014-04-16 08:24:32 +00001778 fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %s -- ", *kbinput, *meta_key ? "TRUE" : "FALSE");
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001779#endif
1780
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001781 /* Check for shortcuts. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001782 for (s = sclist; s != NULL; s = s->next) {
1783 if ((menu & s->menu)
1784 && ((s->type == META && *meta_key == TRUE && *kbinput == s->seq)
1785 || (s->type != META && *kbinput == s->seq))) {
1786#ifdef DEBUG
Benno Schulenberg7828a802014-04-14 09:22:29 +00001787 fprintf (stderr, "matched seq \"%s\", and btw meta was %d (menu is %x from %x)\n",
1788 s->keystr, *meta_key, menu, s->menu);
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001789#endif
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001790 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001791 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001792 }
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001793#ifdef DEBUG
Benno Schulenberg18c252d2014-03-24 20:35:17 +00001794 fprintf (stderr, "matched nothing, btw meta was %d\n", *meta_key);
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001795#endif
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001796
1797 return NULL;
1798}
1799
Benno Schulenberg1e3f6bc2014-04-14 10:03:32 +00001800/* Try to get a function back from a window. Just a wrapper. */
Chris Allegretta0dc26dc2009-01-24 22:40:41 +00001801const subnfunc *getfuncfromkey(WINDOW *win)
1802{
1803 int kbinput;
1804 bool func_key = FALSE, meta_key = FALSE;
1805 const sc *s;
Chris Allegretta0dc26dc2009-01-24 22:40:41 +00001806
1807 kbinput = parse_kbinput(win, &meta_key, &func_key);
1808 if (kbinput == 0)
1809 return NULL;
1810
Benno Schulenberg7828a802014-04-14 09:22:29 +00001811 s = get_shortcut(currmenu, &kbinput, &meta_key);
Chris Allegretta0dc26dc2009-01-24 22:40:41 +00001812 if (!s)
1813 return NULL;
1814
Benno Schulenberg1e3f6bc2014-04-14 10:03:32 +00001815 return sctofunc((sc *) s);
Chris Allegretta0dc26dc2009-01-24 22:40:41 +00001816}
1817
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001818/* Move to (x, y) in win, and display a line of n spaces with the
1819 * current attributes. */
1820void blank_line(WINDOW *win, int y, int x, int n)
1821{
1822 wmove(win, y, x);
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00001823
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001824 for (; n > 0; n--)
1825 waddch(win, ' ');
1826}
1827
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001828/* Blank the first line of the top portion of the window. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001829void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001830{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001831 blank_line(topwin, 0, 0, COLS);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001832}
1833
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001834/* If the MORE_SPACE flag isn't set, blank the second line of the top
1835 * portion of the window. */
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00001836void blank_topbar(void)
1837{
1838 if (!ISSET(MORE_SPACE))
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001839 blank_line(topwin, 1, 0, COLS);
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00001840}
1841
David Lawrence Ramseyb159f942006-07-28 17:06:27 +00001842/* Blank all the lines of the middle portion of the window, i.e. the
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001843 * edit window. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001844void blank_edit(void)
1845{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001846 int i;
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00001847
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001848 for (i = 0; i < editwinrows; i++)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001849 blank_line(edit, i, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001850}
1851
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001852/* Blank the first line of the bottom portion of the window. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001853void blank_statusbar(void)
1854{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001855 blank_line(bottomwin, 0, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001856}
1857
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001858/* If the NO_HELP flag isn't set, blank the last two lines of the bottom
1859 * portion of the window. */
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00001860void blank_bottombars(void)
1861{
1862 if (!ISSET(NO_HELP)) {
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001863 blank_line(bottomwin, 1, 0, COLS);
1864 blank_line(bottomwin, 2, 0, COLS);
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00001865 }
1866}
1867
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001868/* Check if the number of keystrokes needed to blank the statusbar has
1869 * been pressed. If so, blank the statusbar, unless constant cursor
1870 * position display is on. */
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001871void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001872{
David Lawrence Ramsey100bc302006-05-27 18:06:11 +00001873 if (statusblank > 0) {
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001874 statusblank--;
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00001875
David Lawrence Ramsey100bc302006-05-27 18:06:11 +00001876 if (statusblank == 0 && !ISSET(CONST_UPDATE)) {
1877 blank_statusbar();
1878 wnoutrefresh(bottomwin);
1879 reset_cursor();
1880 wnoutrefresh(edit);
1881 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001882 }
1883}
1884
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001885/* Convert buf into a string that can be displayed on screen. The
1886 * caller wants to display buf starting with column start_col, and
1887 * extending for at most len columns. start_col is zero-based. len is
1888 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001889 * string is dynamically allocated, and should be freed. If dollars is
1890 * TRUE, the caller might put "$" at the beginning or end of the line if
1891 * it's too long. */
1892char *display_string(const char *buf, size_t start_col, size_t len, bool
1893 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001894{
1895 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00001896 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001897 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00001898 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001899 size_t alloc_len;
1900 /* The length of memory allocated for converted. */
1901 char *converted;
1902 /* The string we return. */
1903 size_t index;
1904 /* Current position in converted. */
David Lawrence Ramsey1f104f82006-02-03 03:51:51 +00001905 char *buf_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001906 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001907
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00001908 /* If dollars is TRUE, make room for the "$" at the end of the
1909 * line. */
1910 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
1911 len--;
1912
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001913 if (len == 0)
1914 return mallocstrcpy(NULL, "");
1915
David Lawrence Ramsey1f104f82006-02-03 03:51:51 +00001916 buf_mb = charalloc(mb_cur_max());
1917
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001918 start_index = actual_x(buf, start_col);
1919 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001920
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001921 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001922
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001923 /* Make sure there's enough room for the initial character, whether
1924 * it's a multibyte control character, a non-control multibyte
1925 * character, a tab character, or a null terminator. Rationale:
1926 *
1927 * multibyte control character followed by a null terminator:
1928 * 1 byte ('^') + mb_cur_max() bytes + 1 byte ('\0')
1929 * multibyte non-control character followed by a null terminator:
1930 * mb_cur_max() bytes + 1 byte ('\0')
1931 * tab character followed by a null terminator:
1932 * mb_cur_max() bytes + (tabsize - 1) bytes + 1 byte ('\0')
1933 *
1934 * Since tabsize has a minimum value of 1, it can substitute for 1
1935 * byte above. */
1936 alloc_len = (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
1937 converted = charalloc(alloc_len);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00001938
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001939 index = 0;
1940
David Lawrence Ramsey567d4712006-07-05 05:31:21 +00001941 if (buf[start_index] != '\0' && buf[start_index] != '\t' &&
1942 (column < start_col || (dollars && column > 0))) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001943 /* We don't display all of buf[start_index] since it starts to
1944 * the left of the screen. */
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001945 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001946
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001947 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00001948 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001949 char *ctrl_buf_mb = charalloc(mb_cur_max());
1950 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001951
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001952 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
1953 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00001954
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001955 for (i = 0; i < ctrl_buf_mb_len; i++)
1956 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001957
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001958 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001959
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001960 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00001961
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001962 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001963 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00001964 }
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00001965#ifdef ENABLE_UTF8
David Lawrence Ramseyd99b0e12006-05-19 17:50:01 +00001966 else if (using_utf8() && mbwidth(buf_mb) == 2) {
1967 if (column >= start_col) {
1968 converted[index++] = ' ';
1969 start_col++;
1970 }
1971
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00001972 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00001973 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001974
1975 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001976 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00001977#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001978 }
1979
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001980 while (buf[start_index] != '\0') {
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001981 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001982
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001983 /* Make sure there's enough room for the next character, whether
1984 * it's a multibyte control character, a non-control multibyte
1985 * character, a tab character, or a null terminator. */
1986 if (index + mb_cur_max() + tabsize + 1 >= alloc_len - 1) {
1987 alloc_len += (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
1988 converted = charealloc(converted, alloc_len);
1989 }
1990
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00001991 /* If buf contains a tab character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001992 if (*buf_mb == '\t') {
Benno Schulenbergeea09082014-04-13 20:50:20 +00001993#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001994 if (ISSET(WHITESPACE_DISPLAY)) {
1995 int i;
1996
1997 for (i = 0; i < whitespace_len[0]; i++)
1998 converted[index++] = whitespace[i];
1999 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002000#endif
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00002001 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002002 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002003 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002004 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002005 start_col++;
2006 }
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002007 /* If buf contains a control character, interpret it. If buf
David Lawrence Ramsey61f56732005-07-21 22:12:03 +00002008 * contains an invalid multibyte control character, display it
2009 * as such.*/
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002010 } else if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002011 char *ctrl_buf_mb = charalloc(mb_cur_max());
2012 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002013
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002014 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002015 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002016
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002017 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2018 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002019
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002020 for (i = 0; i < ctrl_buf_mb_len; i++)
2021 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002022
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002023 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002024
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002025 free(ctrl_buf_mb);
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002026 /* If buf contains a space character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002027 } else if (*buf_mb == ' ') {
Benno Schulenbergeea09082014-04-13 20:50:20 +00002028#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002029 if (ISSET(WHITESPACE_DISPLAY)) {
2030 int i;
2031
2032 for (i = whitespace_len[0]; i < whitespace_len[0] +
2033 whitespace_len[1]; i++)
2034 converted[index++] = whitespace[i];
2035 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002036#endif
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00002037 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002038 start_col++;
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00002039 /* If buf contains a non-control character, interpret it. If
2040 * buf contains an invalid multibyte non-control character,
2041 * display it as such. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002042 } else {
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00002043 char *nctrl_buf_mb = charalloc(mb_cur_max());
2044 int nctrl_buf_mb_len, i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002045
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00002046 nctrl_buf_mb = mbrep(buf_mb, nctrl_buf_mb,
2047 &nctrl_buf_mb_len);
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002048
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00002049 for (i = 0; i < nctrl_buf_mb_len; i++)
2050 converted[index++] = nctrl_buf_mb[i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002051
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00002052 start_col += mbwidth(nctrl_buf_mb);
2053
2054 free(nctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002055 }
2056
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002057 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002058 }
2059
David Lawrence Ramsey6a0d5b82005-06-13 14:00:22 +00002060 free(buf_mb);
2061
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00002062 assert(alloc_len >= index + 1);
2063
David Lawrence Ramseye54f1c42006-10-29 21:14:53 +00002064 /* Null-terminate converted. */
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00002065 converted[index] = '\0';
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002066
2067 /* Make sure converted takes up no more than len columns. */
2068 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002069 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002070
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002071 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002072}
2073
David Lawrence Ramsey4ea2eac2006-07-09 00:52:16 +00002074/* If path is NULL, we're in normal editing mode, so display the current
2075 * version of nano, the current filename, and whether the current file
2076 * has been modified on the titlebar. If path isn't NULL, we're in the
2077 * file browser, and path contains the directory to start the file
2078 * browser in, so display the current version of nano and the contents
2079 * of path on the titlebar. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00002080void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002081{
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002082 int space = COLS;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002083 /* The space we have available for display. */
David Lawrence Ramsey3c43d3d2006-03-30 01:18:29 +00002084 size_t verlen = strlenpt(PACKAGE_STRING) + 1;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002085 /* The length of the version message in columns, plus one for
2086 * padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002087 const char *prefix;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002088 /* "DIR:", "File:", or "New Buffer". Goes before filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002089 size_t prefixlen;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002090 /* The length of the prefix in columns, plus one for padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002091 const char *state;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002092 /* "Modified", "View", or "". Shows the state of this
2093 * buffer. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002094 size_t statelen = 0;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002095 /* The length of the state in columns, or the length of
David Lawrence Ramsey4ea2eac2006-07-09 00:52:16 +00002096 * "Modified" if the state is blank and we're not in the file
2097 * browser. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002098 char *exppath = NULL;
David Lawrence Ramsey345a5b82006-07-04 03:47:36 +00002099 /* The filename, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002100 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002101 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002102 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002103 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002104
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002105 assert(path != NULL || openfile->filename != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002106
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002107 wattron(topwin, reverse_attr);
David Lawrence Ramsey85ffaee2006-07-02 18:29:49 +00002108
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002109 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002110
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002111 /* space has to be at least 4: two spaces before the version message,
2112 * at least one character of the version message, and one space
2113 * after the version message. */
2114 if (space < 4)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002115 space = 0;
2116 else {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002117 /* Limit verlen to 1/3 the length of the screen in columns,
2118 * minus three columns for spaces. */
2119 if (verlen > (COLS / 3) - 3)
2120 verlen = (COLS / 3) - 3;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002121 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002122
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002123 if (space >= 4) {
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002124 /* Add a space after the version message, and account for both
2125 * it and the two spaces before it. */
David Lawrence Ramsey3c43d3d2006-03-30 01:18:29 +00002126 mvwaddnstr(topwin, 0, 2, PACKAGE_STRING,
2127 actual_x(PACKAGE_STRING, verlen));
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002128 verlen += 3;
2129
2130 /* Account for the full length of the version message. */
2131 space -= verlen;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002132 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002133
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002134#ifndef DISABLE_BROWSER
2135 /* Don't display the state if we're in the file browser. */
2136 if (path != NULL)
2137 state = "";
2138 else
2139#endif
2140 state = openfile->modified ? _("Modified") : ISSET(VIEW_MODE) ?
2141 _("View") : "";
2142
David Lawrence Ramsey1904f512007-07-01 21:33:17 +00002143 statelen = strlenpt((*state == '\0' && path == NULL) ?
David Lawrence Ramseye3281692006-07-09 00:50:23 +00002144 _("Modified") : state);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002145
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002146 /* If possible, add a space before state. */
2147 if (space > 0 && statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002148 statelen++;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002149 else
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002150 goto the_end;
2151
2152#ifndef DISABLE_BROWSER
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002153 /* path should be a directory if we're in the file browser. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002154 if (path != NULL)
2155 prefix = _("DIR:");
2156 else
2157#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002158 if (openfile->filename[0] == '\0') {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002159 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002160 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002161 } else
2162 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002163
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002164 prefixlen = strnlenpt(prefix, space - statelen) + 1;
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002165
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002166 /* If newfie is FALSE, add a space after prefix. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002167 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002168 prefixlen++;
2169
David Lawrence Ramsey4ea2eac2006-07-09 00:52:16 +00002170 /* If we're not in the file browser, set path to the current
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002171 * filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002172 if (path == NULL)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002173 path = openfile->filename;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002174
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002175 /* Account for the full lengths of the prefix and the state. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002176 if (space >= prefixlen + statelen)
2177 space -= prefixlen + statelen;
2178 else
2179 space = 0;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002180 /* space is now the room we have for the filename. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002181
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002182 if (!newfie) {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002183 size_t lenpt = strlenpt(path), start_col;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002184
David Lawrence Ramsey8125e082006-11-25 22:27:22 +00002185 /* Don't set dots to TRUE if we have fewer than eight columns
2186 * (i.e. one column for padding, plus seven columns for a
2187 * filename). */
David Lawrence Ramsey49172ca2006-07-13 02:10:27 +00002188 dots = (space >= 8 && lenpt >= space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002189
2190 if (dots) {
2191 start_col = lenpt - space + 3;
2192 space -= 3;
2193 } else
2194 start_col = 0;
2195
2196 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002197 }
2198
David Lawrence Ramsey85ffaee2006-07-02 18:29:49 +00002199 /* If dots is TRUE, we will display something like "File:
2200 * ...ename". */
2201 if (dots) {
2202 mvwaddnstr(topwin, 0, verlen - 1, prefix, actual_x(prefix,
2203 prefixlen));
2204 if (space <= -3 || newfie)
2205 goto the_end;
2206 waddch(topwin, ' ');
2207 waddnstr(topwin, "...", space + 3);
2208 if (space <= 0)
2209 goto the_end;
2210 waddstr(topwin, exppath);
2211 } else {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002212 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2213 /* The length of the expanded filename. */
2214
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002215 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002216 mvwaddnstr(topwin, 0, verlen + ((space - exppathlen) / 3),
2217 prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002218 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002219 waddch(topwin, ' ');
2220 waddstr(topwin, exppath);
2221 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002222 }
2223
2224 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002225 free(exppath);
2226
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002227 if (state[0] != '\0') {
David Lawrence Ramsey3d12f0f2005-10-26 23:14:59 +00002228 if (statelen >= COLS - 1)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002229 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
2230 else {
David Lawrence Ramseycaa86592005-07-10 23:57:32 +00002231 assert(COLS - statelen - 1 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002232
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002233 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002234 actual_x(state, statelen));
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002235 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002236 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002237
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002238 wattroff(topwin, reverse_attr);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002239
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002240 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002241 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002242 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002243}
2244
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002245/* Mark the current file as modified if it isn't already, and then
2246 * update the titlebar to display the file's new status. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002247void set_modified(void)
2248{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002249 if (!openfile->modified) {
2250 openfile->modified = TRUE;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002251 titlebar(NULL);
Chris Allegretta21f73f92013-01-03 03:07:27 +00002252#ifndef NANO_TINY
Chris Allegrettad70c7f32013-01-03 03:36:20 +00002253 if (ISSET(LOCKING)) {
Chris Allegrettad2f29d02014-01-26 04:09:04 +00002254 if (!strcmp(openfile->filename, ""))
2255 return;
2256 else if (openfile->lock_filename == NULL) {
Chris Allegrettad70c7f32013-01-03 03:36:20 +00002257 /* Translators: Try to keep this at most 80 characters. */
2258 statusbar(_("Warning: Modifying a file which is not locked, check directory permission?"));
2259 } else {
2260 write_lockfile(openfile->lock_filename,
2261 get_full_path(openfile->filename), TRUE);
2262 }
2263 }
Chris Allegretta21f73f92013-01-03 03:07:27 +00002264#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002265 }
2266}
2267
David Lawrence Ramsey5593e202005-06-28 19:49:15 +00002268/* Display a message on the statusbar, and set disable_cursorpos to
2269 * TRUE, so that the message won't be immediately overwritten if
2270 * constant cursor position display is on. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002271void statusbar(const char *msg, ...)
2272{
2273 va_list ap;
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002274 char *bar, *foo;
2275 size_t start_x, foo_len;
Benno Schulenbergeea09082014-04-13 20:50:20 +00002276#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002277 bool old_whitespace;
2278#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002279
2280 va_start(ap, msg);
2281
2282 /* Curses mode is turned off. If we use wmove() now, it will muck
2283 * up the terminal settings. So we just use vfprintf(). */
David Lawrence Ramseyf70f67b2006-06-03 17:31:52 +00002284 if (isendwin()) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002285 vfprintf(stderr, msg, ap);
2286 va_end(ap);
2287 return;
2288 }
2289
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002290 blank_statusbar();
2291
Benno Schulenbergeea09082014-04-13 20:50:20 +00002292#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002293 old_whitespace = ISSET(WHITESPACE_DISPLAY);
2294 UNSET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002295#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002296 bar = charalloc(mb_cur_max() * (COLS - 3));
2297 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
2298 va_end(ap);
2299 foo = display_string(bar, 0, COLS - 4, FALSE);
Benno Schulenbergeea09082014-04-13 20:50:20 +00002300#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002301 if (old_whitespace)
2302 SET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002303#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002304 free(bar);
2305 foo_len = strlenpt(foo);
2306 start_x = (COLS - foo_len - 4) / 2;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002307
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002308 wmove(bottomwin, 0, start_x);
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002309 wattron(bottomwin, reverse_attr);
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002310 waddstr(bottomwin, "[ ");
2311 waddstr(bottomwin, foo);
2312 free(foo);
2313 waddstr(bottomwin, " ]");
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002314 wattroff(bottomwin, reverse_attr);
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002315 wnoutrefresh(bottomwin);
2316 reset_cursor();
2317 wnoutrefresh(edit);
2318 /* Leave the cursor at its position in the edit window, not in
2319 * the statusbar. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002320
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002321 disable_cursorpos = TRUE;
David Lawrence Ramseyc6618532005-06-17 22:33:15 +00002322
2323 /* If we're doing quick statusbar blanking, and constant cursor
2324 * position display is off, blank the statusbar after only one
David Lawrence Ramseyce862362006-05-21 21:23:21 +00002325 * keystroke. Otherwise, blank it after twenty-six keystrokes, as
2326 * Pico does. */
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002327 statusblank =
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002328#ifndef NANO_TINY
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002329 ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 :
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002330#endif
David Lawrence Ramseyce862362006-05-21 21:23:21 +00002331 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002332}
2333
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002334/* Display the shortcut list in s on the last two rows of the bottom
2335 * portion of the window. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002336void bottombars(int menu)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002337{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002338 size_t i, colwidth, slen;
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002339 subnfunc *f;
2340 const sc *s;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002341
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002342 if (ISSET(NO_HELP))
2343 return;
2344
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002345 if (menu == MMAIN) {
Chris Allegretta6232d662002-05-12 19:52:15 +00002346 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002347
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002348 assert(slen <= length_of_list(menu));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002349 } else {
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002350 slen = length_of_list(menu);
Chris Allegretta6232d662002-05-12 19:52:15 +00002351
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002352 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002353 if (slen > MAIN_VISIBLE)
2354 slen = MAIN_VISIBLE;
2355 }
2356
David Lawrence Ramseye806ab82006-04-18 16:13:35 +00002357 /* There will be this many characters per column, except for the
2358 * last two, which will be longer by (COLS % colwidth) columns so as
2359 * to not waste space. We need at least three columns to display
2360 * anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002361 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002362
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002363 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002364
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002365#ifdef DEBUG
2366 fprintf(stderr, "In bottombars, and slen == \"%d\"\n", (int) slen);
2367#endif
Chris Allegretta658399a2001-06-14 02:54:22 +00002368
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002369 for (f = allfuncs, i = 0; i < slen && f != NULL; f = f->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +00002370
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002371#ifdef DEBUG
2372 fprintf(stderr, "Checking menu items....");
2373#endif
2374 if ((f->menus & menu) == 0)
2375 continue;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002376
Chris Allegretta0018d8e2008-03-13 08:23:52 +00002377 if (!f->desc || strlen(f->desc) == 0)
Chris Allegrettaeb643142008-03-12 04:44:14 +00002378 continue;
2379
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002380#ifdef DEBUG
Benno Schulenberg18c252d2014-03-24 20:35:17 +00002381 fprintf(stderr, "found one! f->menus = %x, desc = \"%s\"\n", f->menus, f->desc);
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002382#endif
2383 s = first_sc_for(menu, f->scfunc);
2384 if (s == NULL) {
2385#ifdef DEBUG
2386 fprintf(stderr, "Whoops, guess not, no shortcut key found for func!\n");
2387#endif
2388 continue;
2389 }
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002390 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002391#ifdef DEBUG
2392 fprintf(stderr, "Calling onekey with keystr \"%s\" and desc \"%s\"\n", s->keystr, f->desc);
2393#endif
Chris Allegretta1fb25fd2008-03-18 03:06:27 +00002394 onekey(s->keystr, _(f->desc), colwidth + (COLS % colwidth));
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002395 i++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002396 }
2397
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002398 wnoutrefresh(bottomwin);
2399 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002400 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002401}
2402
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002403/* Write a shortcut key to the help area at the bottom of the window.
2404 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2405 * to write at most len characters, even if len is very small and
2406 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2407 * the whole string! We do not bother padding the entry with blanks. */
2408void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002409{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002410 size_t keystroke_len = strlenpt(keystroke) + 1;
2411
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002412 assert(keystroke != NULL && desc != NULL);
2413
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002414 wattron(bottomwin, reverse_attr);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002415 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002416 wattroff(bottomwin, reverse_attr);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002417
2418 if (len > keystroke_len)
2419 len -= keystroke_len;
2420 else
2421 len = 0;
2422
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002423 if (len > 0) {
2424 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002425 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002426 }
2427}
2428
David Lawrence Ramsey2b9d6a02005-11-01 17:45:31 +00002429/* Reset current_y, based on the position of current, and put the cursor
2430 * in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002431void reset_cursor(void)
2432{
Chris Allegretta05417a22009-08-17 07:52:10 +00002433 size_t xpt;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002434 /* If we haven't opened any files yet, put the cursor in the top
2435 * left corner of the edit window and get out. */
David Lawrence Ramseydbcaa3b2005-07-08 20:59:24 +00002436 if (openfile == NULL) {
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002437 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002438 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002439 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002440
Chris Allegretta05417a22009-08-17 07:52:10 +00002441 xpt = xplustabs();
David Lawrence Ramsey964722a2006-05-26 03:02:50 +00002442
Chris Allegretta05417a22009-08-17 07:52:10 +00002443 if (ISSET(SOFTWRAP)) {
Chris Allegretta05417a22009-08-17 07:52:10 +00002444 filestruct *tmp;
Chris Allegretta6f083322009-11-11 06:00:33 +00002445 openfile->current_y = 0;
Chris Allegretta05417a22009-08-17 07:52:10 +00002446
Chris Allegretta6f083322009-11-11 06:00:33 +00002447 for (tmp = openfile->edittop; tmp && tmp != openfile->current; tmp = tmp->next)
2448 openfile->current_y += 1 + strlenpt(tmp->data) / COLS;
2449
2450 openfile->current_y += xplustabs() / COLS;
Chris Allegretta05417a22009-08-17 07:52:10 +00002451 if (openfile->current_y < editwinrows)
Chris Allegretta6f083322009-11-11 06:00:33 +00002452 wmove(edit, openfile->current_y, xpt % COLS);
Chris Allegretta05417a22009-08-17 07:52:10 +00002453 } else {
2454 openfile->current_y = openfile->current->lineno -
2455 openfile->edittop->lineno;
2456
2457 if (openfile->current_y < editwinrows)
2458 wmove(edit, openfile->current_y, xpt - get_page_start(xpt));
2459 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002460}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002461
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002462/* edit_draw() takes care of the job of actually painting a line into
2463 * the edit window. fileptr is the line to be painted, at row line of
2464 * the window. converted is the actual string to be written to the
2465 * window, with tabs and control characters replaced by strings of
2466 * regular characters. start is the column number of the first
2467 * character of this page. That is, the first character of converted
2468 * corresponds to character number actual_x(fileptr->data, start) of the
2469 * line. */
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002470void edit_draw(filestruct *fileptr, const char *converted, int
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002471 line, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002472{
Benno Schulenberg00389922014-04-04 11:59:03 +00002473#if !defined(NANO_TINY) || !defined(DISABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002474 size_t startpos = actual_x(fileptr->data, start);
2475 /* The position in fileptr->data of the leftmost character
2476 * that displays at least partially on the window. */
2477 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2478 /* The position in fileptr->data of the first character that is
2479 * completely off the window to the right.
2480 *
2481 * Note that endpos might be beyond the null terminator of the
2482 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002483#endif
2484
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002485 assert(openfile != NULL && fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002486 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002487
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002488 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002489 * just the text that needs it). */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002490 mvwaddstr(edit, line, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002491
Benno Schulenberg00389922014-04-04 11:59:03 +00002492#ifndef DISABLE_COLOR
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002493 /* If color syntaxes are available and turned on, we need to display
2494 * them. */
2495 if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
2496 const colortype *tmpcolor = openfile->colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002497
Benno Schulenberg8f615112014-04-14 09:57:06 +00002498 /* Set up multi-line color data for this line if it's not yet calculated. */
Chris Allegretta364763f2009-02-03 05:05:58 +00002499 if (fileptr->multidata == NULL && openfile->syntax
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002500 && openfile->syntax->nmultis > 0) {
Benno Schulenberga65ef422014-03-17 21:36:37 +00002501 int i;
Chris Allegretta5a018f02009-11-29 06:13:22 +00002502 fileptr->multidata = (short *) nmalloc(openfile->syntax->nmultis * sizeof(short));
Chris Allegretta22c83ec2013-03-17 22:09:38 +00002503 for (i = 0; i < openfile->syntax->nmultis; i++)
Benno Schulenberg8f615112014-04-14 09:57:06 +00002504 fileptr->multidata[i] = -1; /* Assume this applies until we know otherwise. */
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002505 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002506 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2507 int x_start;
2508 /* Starting column for mvwaddnstr. Zero-based. */
2509 int paintlen;
David Lawrence Ramsey2ea7fb02006-08-02 18:41:55 +00002510 /* Number of chars to paint on this line. There are
2511 * COLS characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002512 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002513 /* Index in converted where we paint. */
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002514 regmatch_t startmatch;
2515 /* Match position for start_regex. */
2516 regmatch_t endmatch;
2517 /* Match position for end_regex. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002518
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002519 if (tmpcolor->bright)
2520 wattron(edit, A_BOLD);
2521 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramseyb0e04c02005-12-08 07:24:54 +00002522 /* Two notes about regexec(). A return value of zero means
2523 * that there is a match. Also, rm_eo is the first
2524 * non-matching character after the match. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002525
Chris Allegretta22c83ec2013-03-17 22:09:38 +00002526 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002527 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002528 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002529
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002530 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002531 * last match. Even though two matches may overlap, we
David Lawrence Ramsey2ef7dae2006-05-26 11:58:37 +00002532 * want to ignore them, so that we can highlight e.g. C
2533 * strings correctly. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002534 while (k < endpos) {
2535 /* Note the fifth parameter to regexec(). It says
2536 * not to match the beginning-of-line character
David Lawrence Ramsey2ef7dae2006-05-26 11:58:37 +00002537 * unless k is zero. If regexec() returns
2538 * REG_NOMATCH, there are no more matches in the
2539 * line. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002540 if (regexec(tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002541 &startmatch, (k == 0) ? 0 : REG_NOTBOL) ==
2542 REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002543 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002544 /* Translate the match to the beginning of the
2545 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002546 startmatch.rm_so += k;
2547 startmatch.rm_eo += k;
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002548
2549 /* Skip over a zero-length regex match. */
2550 if (startmatch.rm_so == startmatch.rm_eo)
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002551 startmatch.rm_eo++;
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002552 else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002553 startmatch.rm_eo > startpos) {
David Lawrence Ramseyb02a1952006-05-08 16:25:12 +00002554 x_start = (startmatch.rm_so <= startpos) ? 0 :
2555 strnlenpt(fileptr->data,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002556 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002557
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002558 index = actual_x(converted, x_start);
2559
2560 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00002561 strnlenpt(fileptr->data,
2562 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002563
2564 assert(0 <= x_start && 0 <= paintlen);
2565
Chris Allegretta22c83ec2013-03-17 22:09:38 +00002566 mvwaddnstr(edit, line, x_start, converted +
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002567 index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002568 }
Chris Allegretta22c83ec2013-03-17 22:09:38 +00002569 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002570 }
Chris Allegretta56a295b2009-02-07 14:48:30 +00002571 } else if (fileptr->multidata != NULL && fileptr->multidata[tmpcolor->id] != CNONE) {
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002572 /* This is a multi-line regex. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002573 * First, we have to see if the beginning of the line is
2574 * colored by a start on an earlier line, and an end on
2575 * this line or later.
2576 *
2577 * We find the first line before fileptr matching the
2578 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002579 * end, then go to step two. Otherwise, find the next
2580 * line after start_line matching the end. If that line
2581 * is not before fileptr, then paint the beginning of
2582 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002583 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002584 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002585 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002586 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002587 const filestruct *end_line;
Chris Allegretta364763f2009-02-03 05:05:58 +00002588 short md = fileptr->multidata[tmpcolor->id];
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002589
Chris Allegretta364763f2009-02-03 05:05:58 +00002590 if (md == -1)
Chris Allegretta56a295b2009-02-07 14:48:30 +00002591 fileptr->multidata[tmpcolor->id] = CNONE; /* until we find out otherwise */
Chris Allegretta364763f2009-02-03 05:05:58 +00002592 else if (md == CNONE)
2593 continue;
2594 else if (md == CWHOLELINE) {
2595 mvwaddnstr(edit, line, 0, converted, -1);
2596 continue;
Chris Allegretta803379c2009-02-07 07:09:31 +00002597 } else if (md == CBEGINBEFORE) {
2598 regexec(tmpcolor->end, fileptr->data, 1, &endmatch, 0);
2599 paintlen = actual_x(converted, strnlenpt(fileptr->data,
2600 endmatch.rm_eo) - start);
2601 mvwaddnstr(edit, line, 0, converted, paintlen);
2602 continue;
Chris Allegretta364763f2009-02-03 05:05:58 +00002603 }
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002604
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002605 while (start_line != NULL && regexec(tmpcolor->start,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002606 start_line->data, 1, &startmatch, 0) ==
2607 REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002608 /* If there is an end on this line, there is no need
2609 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002610 if (regexec(tmpcolor->end, start_line->data, 0,
2611 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002612 goto step_two;
2613 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002614 }
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002615
2616 /* Skip over a zero-length regex match. */
2617 if (startmatch.rm_so == startmatch.rm_eo)
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002618 startmatch.rm_eo++;
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002619 else {
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002620 /* No start found, so skip to the next step. */
2621 if (start_line == NULL)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002622 goto step_two;
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002623 /* Now start_line is the first line before fileptr
2624 * containing a start match. Is there a start on
2625 * this line not followed by an end on this line? */
2626 start_col = 0;
2627 while (TRUE) {
2628 start_col += startmatch.rm_so;
2629 startmatch.rm_eo -= startmatch.rm_so;
2630 if (regexec(tmpcolor->end, start_line->data +
2631 start_col + startmatch.rm_eo, 0, NULL,
2632 (start_col + startmatch.rm_eo == 0) ?
2633 0 : REG_NOTBOL) == REG_NOMATCH)
2634 /* No end found after this start. */
2635 break;
2636 start_col++;
2637 if (regexec(tmpcolor->start, start_line->data +
2638 start_col, 1, &startmatch,
2639 REG_NOTBOL) == REG_NOMATCH)
2640 /* No later start on this line. */
2641 goto step_two;
2642 }
2643 /* Indeed, there is a start not followed on this
2644 * line by an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002645
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002646 /* We have already checked that there is no end
2647 * before fileptr and after the start. Is there an
2648 * end after the start at all? We don't paint
2649 * unterminated starts. */
2650 end_line = fileptr;
2651 while (end_line != NULL && regexec(tmpcolor->end,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002652 end_line->data, 1, &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002653 end_line = end_line->next;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002654
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002655 /* No end found, or it is too early. */
2656 if (end_line == NULL || (end_line == fileptr &&
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002657 endmatch.rm_eo <= startpos))
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002658 goto step_two;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002659
David Lawrence Ramseycbab2732006-08-02 18:38:45 +00002660 /* Now paint the start of fileptr. If the start of
2661 * fileptr is on a different line from the end,
2662 * paintlen is -1, meaning that everything on the
2663 * line gets painted. Otherwise, paintlen is the
2664 * expanded location of the end of the match minus
2665 * the expanded location of the beginning of the
2666 * page. */
Chris Allegretta364763f2009-02-03 05:05:58 +00002667 if (end_line != fileptr) {
David Lawrence Ramsey1c9dd102006-11-21 17:05:04 +00002668 paintlen = -1;
Chris Allegretta364763f2009-02-03 05:05:58 +00002669 fileptr->multidata[tmpcolor->id] = CWHOLELINE;
2670 } else {
David Lawrence Ramsey1c9dd102006-11-21 17:05:04 +00002671 paintlen = actual_x(converted,
2672 strnlenpt(fileptr->data,
2673 endmatch.rm_eo) - start);
Chris Allegretta364763f2009-02-03 05:05:58 +00002674 fileptr->multidata[tmpcolor->id] = CBEGINBEFORE;
2675 }
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002676 mvwaddnstr(edit, line, 0, converted, paintlen);
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002677 step_two:
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002678 /* Second step, we look for starts on this line. */
2679 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002680
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002681 while (start_col < endpos) {
2682 if (regexec(tmpcolor->start, fileptr->data +
2683 start_col, 1, &startmatch, (start_col ==
2684 0) ? 0 : REG_NOTBOL) == REG_NOMATCH ||
2685 start_col + startmatch.rm_so >= endpos)
2686 /* No more starts on this line. */
2687 break;
2688 /* Translate the match to be relative to the
2689 * beginning of the line. */
2690 startmatch.rm_so += start_col;
2691 startmatch.rm_eo += start_col;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002692
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002693 x_start = (startmatch.rm_so <= startpos) ? 0 :
2694 strnlenpt(fileptr->data,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002695 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002696
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002697 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002698
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002699 if (regexec(tmpcolor->end, fileptr->data +
2700 startmatch.rm_eo, 1, &endmatch,
2701 (startmatch.rm_eo == 0) ? 0 :
2702 REG_NOTBOL) == 0) {
2703 /* Translate the end match to be relative to
2704 * the beginning of the line. */
2705 endmatch.rm_so += startmatch.rm_eo;
2706 endmatch.rm_eo += startmatch.rm_eo;
2707 /* There is an end on this line. But does
2708 * it appear on this page, and is the match
2709 * more than zero characters long? */
2710 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002711 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002712 paintlen = actual_x(converted + index,
2713 strnlenpt(fileptr->data,
2714 endmatch.rm_eo) - start -
2715 x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002716
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002717 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002718
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002719 mvwaddnstr(edit, line, x_start,
2720 converted + index, paintlen);
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002721 if (paintlen > 0)
Chris Allegretta364763f2009-02-03 05:05:58 +00002722 fileptr->multidata[tmpcolor->id] = CSTARTENDHERE;
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002723
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002724 }
2725 } else {
2726 /* There is no end on this line. But we
2727 * haven't yet looked for one on later
2728 * lines. */
2729 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002730
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002731 while (end_line != NULL &&
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002732 regexec(tmpcolor->end, end_line->data,
2733 0, NULL, 0) == REG_NOMATCH)
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002734 end_line = end_line->next;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002735
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002736 if (end_line != NULL) {
2737 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002738
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002739 mvwaddnstr(edit, line, x_start,
2740 converted + index, -1);
2741 /* We painted to the end of the line, so
2742 * don't bother checking any more
2743 * starts. */
Chris Allegretta364763f2009-02-03 05:05:58 +00002744 fileptr->multidata[tmpcolor->id] = CENDAFTER;
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002745 break;
2746 }
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002747 }
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002748 start_col = startmatch.rm_so + 1;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002749 }
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002750 }
2751 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002752
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002753 wattroff(edit, A_BOLD);
2754 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002755 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002756 }
Benno Schulenberg00389922014-04-04 11:59:03 +00002757#endif /* !DISABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002758
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002759#ifndef NANO_TINY
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002760 /* If the mark is on, we need to display it. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002761 if (openfile->mark_set && (fileptr->lineno <=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002762 openfile->mark_begin->lineno || fileptr->lineno <=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002763 openfile->current->lineno) && (fileptr->lineno >=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002764 openfile->mark_begin->lineno || fileptr->lineno >=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002765 openfile->current->lineno)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002766 /* fileptr is at least partially selected. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002767 const filestruct *top;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002768 /* Either current or mark_begin, whichever is first. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002769 size_t top_x;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002770 /* current_x or mark_begin_x, corresponding to top. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002771 const filestruct *bot;
2772 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002773 int x_start;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002774 /* Starting column for mvwaddnstr(). Zero-based. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002775 int paintlen;
David Lawrence Ramseyc6bef762006-08-02 19:13:31 +00002776 /* Number of characters to paint on this line. There are
2777 * COLS characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002778 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002779 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002780
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00002781 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002782
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002783 if (top->lineno < fileptr->lineno || top_x < startpos)
2784 top_x = startpos;
2785 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2786 bot_x = endpos;
2787
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002788 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002789 if (top_x < endpos && bot_x > startpos) {
2790 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002791
2792 /* x_start is the expanded location of the beginning of the
2793 * mark minus the beginning of the page. */
2794 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002795
David Lawrence Ramseycbab2732006-08-02 18:38:45 +00002796 /* If the end of the mark is off the page, paintlen is -1,
2797 * meaning that everything on the line gets painted.
2798 * Otherwise, paintlen is the expanded location of the end
2799 * of the mark minus the expanded location of the beginning
2800 * of the mark. */
David Lawrence Ramsey1c9dd102006-11-21 17:05:04 +00002801 if (bot_x >= endpos)
2802 paintlen = -1;
2803 else
2804 paintlen = strnlenpt(fileptr->data, bot_x) - (x_start +
2805 start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002806
2807 /* If x_start is before the beginning of the page, shift
2808 * paintlen x_start characters to compensate, and put
2809 * x_start at the beginning of the page. */
2810 if (x_start < 0) {
2811 paintlen += x_start;
2812 x_start = 0;
2813 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002814
2815 assert(x_start >= 0 && x_start <= strlen(converted));
2816
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002817 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002818
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002819 if (paintlen > 0)
2820 paintlen = actual_x(converted + index, paintlen);
2821
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002822 wattron(edit, reverse_attr);
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002823 mvwaddnstr(edit, line, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00002824 paintlen);
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002825 wattroff(edit, reverse_attr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002826 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002827 }
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002828#endif /* !NANO_TINY */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002829}
2830
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002831/* Just update one line in the edit buffer. This is basically a wrapper
David Lawrence Ramseyb3c6b402005-11-07 06:20:02 +00002832 * for edit_draw(). The line will be displayed starting with
Chris Allegretta05417a22009-08-17 07:52:10 +00002833 * fileptr->data[index]. Likely arguments are current_x or zero.
Benno Schulenbergd0dec312014-04-08 12:35:18 +00002834 * Returns: Number of additional lines consumed (needed for SOFTWRAP). */
Chris Allegretta05417a22009-08-17 07:52:10 +00002835int update_line(filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002836{
Chris Allegretta05417a22009-08-17 07:52:10 +00002837 int line = 0;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002838 /* The line in the edit window that we want to update. */
Benno Schulenbergf876ee12014-04-15 11:25:29 +00002839 int extralinesused = 0;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002840 char *converted;
2841 /* fileptr->data converted to have tabs and control characters
2842 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002843 size_t page_start;
Chris Allegretta05417a22009-08-17 07:52:10 +00002844 filestruct *tmp;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002845
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002846 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002847
Chris Allegretta05417a22009-08-17 07:52:10 +00002848 if (ISSET(SOFTWRAP)) {
Chris Allegretta139934a2009-08-30 03:50:16 +00002849 for (tmp = openfile->edittop; tmp && tmp != fileptr; tmp = tmp->next) {
Chris Allegretta05417a22009-08-17 07:52:10 +00002850 line += 1 + (strlenpt(tmp->data) / COLS);
Chris Allegretta05417a22009-08-17 07:52:10 +00002851 }
2852 } else
2853 line = fileptr->lineno - openfile->edittop->lineno;
2854
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002855 if (line < 0 || line >= editwinrows)
Chris Allegrettad233e7e2009-09-15 04:51:09 +00002856 return 1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002857
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002858 /* First, blank out the line. */
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002859 blank_line(edit, line, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002860
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002861 /* Next, convert variables that index the line to their equivalent
2862 * positions in the expanded line. */
Chris Allegretta05417a22009-08-17 07:52:10 +00002863 if (ISSET(SOFTWRAP))
2864 index = 0;
2865 else
2866 index = strnlenpt(fileptr->data, index);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002867 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002868
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002869 /* Expand the line, replacing tabs with spaces, and control
2870 * characters with their displayed forms. */
Chris Allegretta6f083322009-11-11 06:00:33 +00002871 converted = display_string(fileptr->data, page_start, COLS, !ISSET(SOFTWRAP));
2872
2873#ifdef DEBUG
2874 if (ISSET(SOFTWRAP) && strlen(converted) >= COLS - 2)
2875 fprintf(stderr, "update_line(): converted(1) line = %s\n", converted);
2876#endif
2877
Robert Siemborski53875912000-06-16 04:25:30 +00002878
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002879 /* Paint the line. */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002880 edit_draw(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002881 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002882
Chris Allegretta05417a22009-08-17 07:52:10 +00002883 if (!ISSET(SOFTWRAP)) {
2884 if (page_start > 0)
2885 mvwaddch(edit, line, 0, '$');
2886 if (strlenpt(fileptr->data) > page_start + COLS)
2887 mvwaddch(edit, line, COLS - 1, '$');
2888 } else {
2889 int full_length = strlenpt(fileptr->data);
Chris Allegretta6f083322009-11-11 06:00:33 +00002890 for (index += COLS; index <= full_length && line < editwinrows; index += COLS) {
Chris Allegretta05417a22009-08-17 07:52:10 +00002891 line++;
2892#ifdef DEBUG
Chris Allegretta6f083322009-11-11 06:00:33 +00002893 fprintf(stderr, "update_line(): Softwrap code, moving to %d index %lu\n", line, (unsigned long) index);
Chris Allegretta05417a22009-08-17 07:52:10 +00002894#endif
2895 blank_line(edit, line, 0, COLS);
2896
2897 /* Expand the line, replacing tabs with spaces, and control
2898 * characters with their displayed forms. */
Chris Allegretta6f083322009-11-11 06:00:33 +00002899 converted = display_string(fileptr->data, index, COLS, !ISSET(SOFTWRAP));
2900#ifdef DEBUG
2901 if (ISSET(SOFTWRAP) && strlen(converted) >= COLS - 2)
2902 fprintf(stderr, "update_line(): converted(2) line = %s\n", converted);
2903#endif
Chris Allegretta05417a22009-08-17 07:52:10 +00002904
2905 /* Paint the line. */
2906 edit_draw(fileptr, converted, line, index);
2907 free(converted);
2908 extralinesused++;
2909 }
2910 }
2911 return extralinesused;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002912}
2913
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002914/* Return TRUE if we need an update after moving horizontally, and FALSE
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002915 * otherwise. We need one if the mark is on or if pww_save and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002916 * placewewant are on different pages. */
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002917bool need_horizontal_update(size_t pww_save)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002918{
2919 return
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002920#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002921 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002922#endif
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002923 get_page_start(pww_save) !=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002924 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002925}
2926
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002927/* Return TRUE if we need an update after moving vertically, and FALSE
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002928 * otherwise. We need one if the mark is on or if pww_save and
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002929 * placewewant are on different pages. */
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002930bool need_vertical_update(size_t pww_save)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002931{
2932 return
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002933#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002934 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002935#endif
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002936 get_page_start(pww_save) !=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002937 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002938}
2939
Chris Allegretta99c8d402009-11-13 13:48:56 +00002940/* When edittop changes, try and figure out how many lines
Benno Schulenbergd0dec312014-04-08 12:35:18 +00002941 * we really have to work with (i.e. set maxrows). */
Chris Allegretta99c8d402009-11-13 13:48:56 +00002942void compute_maxrows(void)
2943{
2944 int n;
2945 filestruct *foo = openfile->edittop;
2946
Chris Allegretta8c1edd12009-11-16 04:28:40 +00002947 if (!ISSET(SOFTWRAP)) {
2948 maxrows = editwinrows;
2949 return;
2950 }
2951
Chris Allegretta99c8d402009-11-13 13:48:56 +00002952 maxrows = 0;
2953 for (n = 0; n < editwinrows && foo; n++) {
Benno Schulenbergd0dec312014-04-08 12:35:18 +00002954 maxrows++;
Chris Allegrettae2df2c82009-11-24 17:15:53 +00002955 n += strlenpt(foo->data) / COLS;
Chris Allegretta99c8d402009-11-13 13:48:56 +00002956 foo = foo->next;
2957 }
2958
Chris Allegretta8c1edd12009-11-16 04:28:40 +00002959 if (n < editwinrows)
2960 maxrows += editwinrows - n;
2961
Chris Allegretta99c8d402009-11-13 13:48:56 +00002962#ifdef DEBUG
Benno Schulenberg55a0d762014-03-24 13:35:50 +00002963 fprintf(stderr, "compute_maxrows(): maxrows = %i\n", maxrows);
Chris Allegretta99c8d402009-11-13 13:48:56 +00002964#endif
Chris Allegretta99c8d402009-11-13 13:48:56 +00002965}
2966
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002967/* Scroll the edit window in the given direction and the given number
2968 * of lines, and draw new lines on the blank lines left after the
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00002969 * scrolling. direction is the direction to scroll, either UP_DIR or
2970 * DOWN_DIR, and nlines is the number of lines to scroll. We change
2971 * edittop, and assume that current and current_x are up to date. We
2972 * also assume that scrollok(edit) is FALSE. */
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002973void edit_scroll(scroll_dir direction, ssize_t nlines)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002974{
Benno Schulenberga8353bd2014-03-17 13:15:50 +00002975 ssize_t i;
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002976 filestruct *foo;
Chris Allegretta139934a2009-08-30 03:50:16 +00002977 bool do_redraw = FALSE;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002978
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002979 /* Don't bother scrolling less than one line. */
2980 if (nlines < 1)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002981 return;
2982
Chris Allegretta5687c3d2009-09-03 02:48:35 +00002983 if (need_vertical_update(0))
Chris Allegretta139934a2009-08-30 03:50:16 +00002984 do_redraw = TRUE;
2985
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002986 /* Part 1: nlines is the number of lines we're going to scroll the
2987 * text of the edit window. */
2988
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002989 /* Move the top line of the edit window up or down (depending on the
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002990 * value of direction) nlines lines, or as many lines as we can if
2991 * there are fewer than nlines lines available. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002992 for (i = nlines; i > 0; i--) {
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00002993 if (direction == UP_DIR) {
David Lawrence Ramseye99223d2005-11-10 04:27:30 +00002994 if (openfile->edittop == openfile->fileage)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002995 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002996 openfile->edittop = openfile->edittop->prev;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002997 } else {
David Lawrence Ramseye99223d2005-11-10 04:27:30 +00002998 if (openfile->edittop == openfile->filebot)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002999 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003000 openfile->edittop = openfile->edittop->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003001 }
Benno Schulenbergf876ee12014-04-15 11:25:29 +00003002 /* Don't over-scroll on long lines. */
Benno Schulenbergb1a7fdd2014-03-03 10:02:13 +00003003 if (ISSET(SOFTWRAP) && (direction == UP_DIR)) {
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003004 ssize_t len = strlenpt(openfile->edittop->data) / COLS;
3005 i -= len;
3006 if (len > 0)
3007 do_redraw = TRUE;
3008 }
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003009 }
3010
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00003011 /* Limit nlines to the number of lines we could scroll. */
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00003012 nlines -= i;
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00003013
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00003014 /* Don't bother scrolling zero lines or more than the number of
3015 * lines in the edit window minus one; in both cases, get out, and
David Lawrence Ramsey1072fce2007-09-16 16:53:20 +00003016 * call edit_refresh() beforehand if we need to. */
Chris Allegretta139934a2009-08-30 03:50:16 +00003017 if (nlines == 0 || do_redraw || nlines >= editwinrows) {
David Lawrence Ramsey1072fce2007-09-16 16:53:20 +00003018 if (do_redraw || nlines >= editwinrows)
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003019 edit_refresh_needed = TRUE;
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00003020 return;
3021 }
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003022
3023 /* Scroll the text of the edit window up or down nlines lines,
3024 * depending on the value of direction. */
David Lawrence Ramsey47bb8882005-07-22 22:56:03 +00003025 scrollok(edit, TRUE);
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00003026 wscrl(edit, (direction == UP_DIR) ? -nlines : nlines);
David Lawrence Ramsey47bb8882005-07-22 22:56:03 +00003027 scrollok(edit, FALSE);
3028
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003029 /* Part 2: nlines is the number of lines in the scrolled region of
3030 * the edit window that we need to draw. */
3031
David Lawrence Ramsey68346502005-08-16 03:03:15 +00003032 /* If the top or bottom line of the file is now visible in the edit
3033 * window, we need to draw the entire edit window. */
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00003034 if ((direction == UP_DIR && openfile->edittop ==
3035 openfile->fileage) || (direction == DOWN_DIR &&
3036 openfile->edittop->lineno + editwinrows - 1 >=
3037 openfile->filebot->lineno))
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00003038 nlines = editwinrows;
David Lawrence Ramseya7f488b2005-07-17 02:19:47 +00003039
David Lawrence Ramseya6eb8482006-01-10 07:51:49 +00003040 /* If the scrolled region contains only one line, and the line
3041 * before it is visible in the edit window, we need to draw it too.
3042 * If the scrolled region contains more than one line, and the lines
3043 * before and after the scrolled region are visible in the edit
3044 * window, we need to draw them too. */
3045 nlines += (nlines == 1) ? 1 : 2;
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00003046
David Lawrence Ramseyde0c5eb2005-07-17 22:51:44 +00003047 if (nlines > editwinrows)
3048 nlines = editwinrows;
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003049
3050 /* If we scrolled up, we're on the line before the scrolled
3051 * region. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003052 foo = openfile->edittop;
David Lawrence Ramsey14588912005-07-14 20:37:01 +00003053
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003054 /* If we scrolled down, move down to the line before the scrolled
3055 * region. */
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00003056 if (direction == DOWN_DIR) {
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003057 for (i = editwinrows - nlines; i > 0 && foo != NULL; i--)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003058 foo = foo->next;
3059 }
3060
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003061 /* Draw new lines on any blank lines before or inside the scrolled
3062 * region. If we scrolled down and we're on the top line, or if we
3063 * scrolled up and we're on the bottom line, the line won't be
3064 * blank, so we don't need to draw it unless the mark is on or we're
3065 * not on the first page. */
3066 for (i = nlines; i > 0 && foo != NULL; i--) {
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00003067 if ((i == nlines && direction == DOWN_DIR) || (i == 1 &&
3068 direction == UP_DIR)) {
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003069 if (do_redraw)
3070 update_line(foo, (foo == openfile->current) ?
3071 openfile->current_x : 0);
3072 } else
3073 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003074 openfile->current_x : 0);
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003075 foo = foo->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003076 }
Benno Schulenbergdf7bba32014-02-26 11:38:30 +00003077 compute_maxrows();
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003078}
3079
3080/* Update any lines between old_current and current that need to be
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00003081 * updated. Use this if we've moved without changing any text. */
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00003082void edit_redraw(filestruct *old_current, size_t pww_save)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003083{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003084 bool do_redraw = need_vertical_update(0) ||
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00003085 need_vertical_update(pww_save);
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00003086 filestruct *foo = NULL;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003087
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003088 /* If either old_current or current is offscreen, scroll the edit
3089 * window until it's onscreen and get out. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003090 if (old_current->lineno < openfile->edittop->lineno ||
3091 old_current->lineno >= openfile->edittop->lineno +
Chris Allegretta99c8d402009-11-13 13:48:56 +00003092 maxrows || openfile->current->lineno <
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003093 openfile->edittop->lineno || openfile->current->lineno >=
Chris Allegretta99c8d402009-11-13 13:48:56 +00003094 openfile->edittop->lineno + maxrows) {
Chris Allegretta139934a2009-08-30 03:50:16 +00003095
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003096#ifdef DEBUG
Benno Schulenberg55a0d762014-03-24 13:35:50 +00003097 fprintf(stderr, "edit_redraw(): line %d was offscreen, oldcurrent = %d edittop = %d",
3098 openfile->current->lineno, old_current->lineno, openfile->edittop->lineno);
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003099#endif
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003100
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003101#ifndef NANO_TINY
3102 /* If the mark is on, update all the lines between old_current
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003103 * and either the old first line or old last line (depending on
3104 * whether we've scrolled up or down) of the edit window. */
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003105 if (openfile->mark_set) {
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003106 ssize_t old_lineno;
Chris Allegretta4cc24622013-01-03 04:23:10 +00003107 filestruct *old_edittop = openfile->edittop;
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003108
3109 if (old_edittop->lineno < openfile->edittop->lineno)
3110 old_lineno = old_edittop->lineno;
3111 else
Chris Allegretta99c8d402009-11-13 13:48:56 +00003112 old_lineno = (old_edittop->lineno + maxrows <=
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003113 openfile->filebot->lineno) ?
3114 old_edittop->lineno + editwinrows :
3115 openfile->filebot->lineno;
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003116
3117 foo = old_current;
3118
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003119 while (foo->lineno != old_lineno) {
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003120 update_line(foo, 0);
3121
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003122 foo = (foo->lineno > old_lineno) ? foo->prev :
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003123 foo->next;
3124 }
3125 }
3126#endif /* !NANO_TINY */
3127
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003128 /* Put edittop in range of current, get the difference in lines
3129 * between the original edittop and the current edittop, and
3130 * then restore the original edittop. */
Chris Allegretta374216f2010-01-04 19:00:55 +00003131 edit_update(CENTER);
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003132
David Lawrence Ramseyb0063672006-07-06 18:29:37 +00003133 /* Update old_current if we're not on the same page as
3134 * before. */
David Lawrence Ramseya6eb8482006-01-10 07:51:49 +00003135 if (do_redraw)
3136 update_line(old_current, 0);
3137
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003138#ifndef NANO_TINY
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003139 /* If the mark is on, update all the lines between the old first
3140 * line or old last line of the edit window (depending on
3141 * whether we've scrolled up or down) and current. */
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003142 if (openfile->mark_set) {
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003143 while (foo->lineno != openfile->current->lineno) {
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003144 update_line(foo, 0);
3145
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003146 foo = (foo->lineno > openfile->current->lineno) ?
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003147 foo->prev : foo->next;
3148 }
3149 }
3150#endif /* !NANO_TINY */
3151
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003152 return;
3153 }
3154
David Lawrence Ramseyb0063672006-07-06 18:29:37 +00003155 /* Update old_current and current if we're not on the same page as
3156 * before. If the mark is on, update all the lines between
3157 * old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003158 foo = old_current;
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003159
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003160 while (foo != openfile->current) {
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003161 if (do_redraw)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003162 update_line(foo, 0);
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003163
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00003164#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003165 if (!openfile->mark_set)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003166#endif
3167 break;
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003168
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00003169#ifndef NANO_TINY
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003170 foo = (foo->lineno > openfile->current->lineno) ? foo->prev :
3171 foo->next;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003172#endif
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003173 }
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003174
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003175 if (do_redraw)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003176 update_line(openfile->current, openfile->current_x);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003177}
3178
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00003179/* Refresh the screen without changing the position of lines. Use this
3180 * if we've moved and changed text. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003181void edit_refresh(void)
3182{
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00003183 filestruct *foo;
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003184 int nlines;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003185
Benno Schulenbergf876ee12014-04-15 11:25:29 +00003186 /* Figure out what maxrows should really be. */
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003187 compute_maxrows();
Chris Allegretta99c8d402009-11-13 13:48:56 +00003188
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003189 if (openfile->current->lineno < openfile->edittop->lineno ||
3190 openfile->current->lineno >= openfile->edittop->lineno +
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003191 maxrows) {
3192
3193#ifdef DEBUG
3194 fprintf(stderr, "edit_refresh(): line = %d, edittop %d + maxrows %d\n", openfile->current->lineno, openfile->edittop->lineno, maxrows);
3195#endif
3196
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003197 /* Put the top line of the edit window in range of the current
3198 * line. */
Chris Allegretta374216f2010-01-04 19:00:55 +00003199 edit_update(CENTER);
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003200 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003201
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003202 foo = openfile->edittop;
3203
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003204#ifdef DEBUG
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003205 fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", (long)openfile->edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003206#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003207
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003208 for (nlines = 0; nlines < editwinrows && foo != NULL; nlines++) {
Chris Allegretta05417a22009-08-17 07:52:10 +00003209 nlines += update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003210 openfile->current_x : 0);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003211 foo = foo->next;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003212 }
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003213
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003214 for (; nlines < editwinrows; nlines++)
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003215 blank_line(edit, nlines, 0, COLS);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003216
3217 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00003218 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003219}
3220
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003221/* Move edittop to put it in range of current, keeping current in the
3222 * same place. location determines how we move it: if it's CENTER, we
3223 * center current, and if it's NONE, we put current current_y lines
3224 * below edittop. */
David Lawrence Ramseybf0e47d2005-08-01 18:27:10 +00003225void edit_update(update_type location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003226{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003227 filestruct *foo = openfile->current;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003228 int goal;
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003229
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003230 /* If location is CENTER, we move edittop up (editwinrows / 2)
3231 * lines. This puts current at the center of the screen. If
3232 * location is NONE, we move edittop up current_y lines if current_y
3233 * is in range of the screen, 0 lines if current_y is less than 0,
3234 * or (editwinrows - 1) lines if current_y is greater than
3235 * (editwinrows - 1). This puts current at the same place on the
3236 * screen as before, or at the top or bottom of the screen if
3237 * edittop is beyond either. */
3238 if (location == CENTER)
Chris Allegretta374216f2010-01-04 19:00:55 +00003239 goal = editwinrows / 2;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003240 else {
3241 goal = openfile->current_y;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003242
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003243 /* Limit goal to (editwinrows - 1) lines maximum. */
Chris Allegretta374216f2010-01-04 19:00:55 +00003244 if (goal > editwinrows - 1)
3245 goal = editwinrows - 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003246 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003247
Chris Allegretta35afab52009-09-13 04:50:44 +00003248 for (; goal > 0 && foo->prev != NULL; goal--) {
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003249 foo = foo->prev;
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003250 if (ISSET(SOFTWRAP) && foo)
3251 goal -= strlenpt(foo->data) / COLS;
Chris Allegretta35afab52009-09-13 04:50:44 +00003252 }
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003253 openfile->edittop = foo;
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003254#ifdef DEBUG
3255 fprintf(stderr, "edit_udpate(), setting edittop to lineno %d\n", openfile->edittop->lineno);
3256#endif
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003257 compute_maxrows();
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003258 edit_refresh_needed = TRUE;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003259}
3260
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003261/* Unconditionally redraw the entire screen. */
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003262void total_redraw(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003263{
David Lawrence Ramseyf78bc852007-12-18 15:55:48 +00003264#ifdef USE_SLANG
3265 /* Slang curses emulation brain damage, part 4: Slang doesn't define
3266 * curscr. */
3267 SLsmg_touch_screen();
3268 SLsmg_refresh();
3269#else
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00003270 wrefresh(curscr);
David Lawrence Ramseyf78bc852007-12-18 15:55:48 +00003271#endif
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003272}
3273
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003274/* Unconditionally redraw the entire screen, and then refresh it using
3275 * the current file. */
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003276void total_refresh(void)
3277{
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003278 total_redraw();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003279 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003280 edit_refresh();
Chris Allegretta79a33bb2008-03-05 07:34:01 +00003281 bottombars(currmenu);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003282}
3283
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003284/* Display the main shortcut list on the last two rows of the bottom
3285 * portion of the window. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003286void display_main_list(void)
3287{
Benno Schulenberg00389922014-04-04 11:59:03 +00003288#ifndef DISABLE_COLOR
Chris Allegretta5575bfa2014-02-24 10:18:15 +00003289 if (openfile->syntax && openfile->syntax->linter)
3290 set_lint_shortcuts();
3291 else
3292 set_spell_shortcuts();
3293#endif
3294
Chris Allegretta79a33bb2008-03-05 07:34:01 +00003295 bottombars(MMAIN);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003296}
3297
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003298/* If constant is TRUE, we display the current cursor position only if
3299 * disable_cursorpos is FALSE. Otherwise, we display it
3300 * unconditionally and set disable_cursorpos to FALSE. If constant is
3301 * TRUE and disable_cursorpos is TRUE, we also set disable_cursorpos to
3302 * FALSE, so that we leave the current statusbar alone this time, and
3303 * display the current cursor position next time. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003304void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003305{
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003306 filestruct *f;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003307 char c;
David Lawrence Ramsey5745c0a2005-07-31 20:20:37 +00003308 size_t i, cur_xpt = xplustabs() + 1;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003309 size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003310 int linepct, colpct, charpct;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003311
David Lawrence Ramsey4ab80152005-07-31 18:51:51 +00003312 assert(openfile->fileage != NULL && openfile->current != NULL);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003313
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003314 f = openfile->current->next;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003315 c = openfile->current->data[openfile->current_x];
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003316
3317 openfile->current->next = NULL;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003318 openfile->current->data[openfile->current_x] = '\0';
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003319
3320 i = get_totsize(openfile->fileage, openfile->current);
3321
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003322 openfile->current->data[openfile->current_x] = c;
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003323 openfile->current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003324
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003325 if (constant && disable_cursorpos) {
3326 disable_cursorpos = FALSE;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003327 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003328 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003329
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00003330 /* Display the current cursor position on the statusbar, and set
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003331 * disable_cursorpos to FALSE. */
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003332 linepct = 100 * openfile->current->lineno /
3333 openfile->filebot->lineno;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003334 colpct = 100 * cur_xpt / cur_lenpt;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003335 charpct = (openfile->totsize == 0) ? 0 : 100 * i /
3336 openfile->totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003337
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003338 statusbar(
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003339 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003340 (long)openfile->current->lineno,
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003341 (long)openfile->filebot->lineno, linepct,
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003342 (unsigned long)cur_xpt, (unsigned long)cur_lenpt, colpct,
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003343 (unsigned long)i, (unsigned long)openfile->totsize, charpct);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003344
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003345 disable_cursorpos = FALSE;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003346}
3347
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003348/* Unconditionally display the current cursor position. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003349void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003350{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003351 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003352}
3353
Chris Allegretta0dc26dc2009-01-24 22:40:41 +00003354void enable_nodelay(void)
3355{
3356 nodelay_mode = TRUE;
3357 nodelay(edit, TRUE);
3358}
3359
3360void disable_nodelay(void)
3361{
3362 nodelay_mode = FALSE;
3363 nodelay(edit, FALSE);
3364}
3365
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003366/* Highlight the current word being replaced or spell checked. We
3367 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003368void do_replace_highlight(bool highlight, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003369{
David Lawrence Ramsey6168cb72005-06-30 03:53:28 +00003370 size_t y = xplustabs(), word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003371
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003372 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003373 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003374 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003375
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003376 assert(y > 0);
3377
3378 if (word_len > y)
3379 y--;
3380
Chris Allegrettafb62f732000-12-05 11:36:41 +00003381 reset_cursor();
David Lawrence Ramsey98958e82007-12-04 16:38:47 +00003382 wnoutrefresh(edit);
Chris Allegretta598106e2002-01-19 01:59:37 +00003383
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003384 if (highlight)
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00003385 wattron(edit, reverse_attr);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003386
David Lawrence Ramsey21b946e2006-11-10 20:13:38 +00003387 /* This is so we can show zero-length matches. */
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003388 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00003389 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003390 else
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003391 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003392
3393 if (word_len > y)
3394 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003395
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003396 if (highlight)
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00003397 wattroff(edit, reverse_attr);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003398}
3399
Benno Schulenbergd17438b2014-04-03 20:57:44 +00003400#ifndef DISABLE_EXTRA
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003401#define CREDIT_LEN 57
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003402#define XLCREDIT_LEN 8
3403
David Lawrence Ramsey8ad58bc2005-08-16 03:02:46 +00003404/* Easter egg: Display credits. Assume nodelay(edit) and scrollok(edit)
3405 * are FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003406void do_credits(void)
3407{
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003408 bool old_more_space = ISSET(MORE_SPACE);
3409 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003410 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003411 const char *credits[CREDIT_LEN] = {
3412 NULL, /* "The nano text editor" */
3413 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003414 VERSION,
3415 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003416 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003417 "Chris Allegretta",
3418 "Jordi Mallach",
3419 "Adam Rogoyski",
3420 "Rob Siemborski",
3421 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003422 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003423 "David Benbennick",
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003424 "Mike Frysinger",
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003425 "Benno Schulenberg",
Chris Allegretta598106e2002-01-19 01:59:37 +00003426 "Ken Tyler",
3427 "Sven Guckes",
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003428 NULL, /* credits[16], handled below. */
Chris Allegretta598106e2002-01-19 01:59:37 +00003429 "Pauli Virtanen",
3430 "Daniele Medri",
3431 "Clement Laforet",
3432 "Tedi Heriyanto",
3433 "Bill Soudan",
3434 "Christian Weisgerber",
3435 "Erik Andersen",
3436 "Big Gaute",
3437 "Joshua Jensen",
3438 "Ryan Krebs",
3439 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003440 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003441 NULL, /* "Special thanks to:" */
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003442 "Monique, Brielle & Joseph",
Chris Allegretta598106e2002-01-19 01:59:37 +00003443 "Plattsburgh State University",
3444 "Benet Laboratories",
3445 "Amy Allegretta",
3446 "Linda Young",
3447 "Jeremy Robichaud",
3448 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003449 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003450 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003451 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003452 "Thomas Dickey",
3453 "Pavel Curtis",
3454 "Zeyd Ben-Halim",
3455 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003456 NULL, /* "and anyone else we forgot..." */
3457 NULL, /* "Thank you for using nano!" */
3458 "",
3459 "",
3460 "",
3461 "",
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003462 "(C) 1999 - 2014",
David Lawrence Ramseyd8a1d372007-10-11 05:01:32 +00003463 "Free Software Foundation, Inc.",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003464 "",
3465 "",
3466 "",
3467 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003468 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003469 };
3470
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003471 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003472 N_("The nano text editor"),
3473 N_("version"),
3474 N_("Brought to you by:"),
3475 N_("Special thanks to:"),
3476 N_("The Free Software Foundation"),
3477 N_("For ncurses:"),
3478 N_("and anyone else we forgot..."),
3479 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003480 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003481
Benno Schulenbergd0dec312014-04-08 12:35:18 +00003482 /* credits[16]: Make sure this name is displayed properly, since we
David Lawrence Ramsey62d616b2005-07-06 19:20:32 +00003483 * can't dynamically assign it above, using Unicode 00F6 (Latin
3484 * Small Letter O with Diaresis) if applicable. */
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003485 credits[16] =
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00003486#ifdef ENABLE_UTF8
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00003487 using_utf8() ? "Florian K\xC3\xB6nig" :
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003488#endif
3489 "Florian K\xF6nig";
3490
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003491 if (!old_more_space || !old_no_help) {
3492 SET(MORE_SPACE);
3493 SET(NO_HELP);
3494 window_init();
3495 }
3496
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003497 curs_set(0);
3498 nodelay(edit, TRUE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003499
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003500 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003501 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003502 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003503 blank_statusbar();
3504 blank_bottombars();
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003505
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003506 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003507 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003508 wrefresh(bottomwin);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003509 napms(700);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003510
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003511 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003512 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003513 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003514
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003515 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003516 const char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003517 size_t start_x;
3518
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003519 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003520 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003521
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003522 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003523 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003524 } else
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003525 what = credits[crpos];
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003526
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003527 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003528 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
3529 start_x, what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003530 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003531
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003532 wrefresh(edit);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003533
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003534 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003535 break;
3536 napms(700);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003537
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003538 scrollok(edit, TRUE);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003539 wscrl(edit, 1);
3540 scrollok(edit, FALSE);
3541 wrefresh(edit);
3542
3543 if ((kbinput = wgetch(edit)) != ERR)
3544 break;
3545 napms(700);
3546
3547 scrollok(edit, TRUE);
3548 wscrl(edit, 1);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003549 scrollok(edit, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003550 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003551 }
3552
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003553 if (kbinput != ERR)
3554 ungetch(kbinput);
3555
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003556 if (!old_more_space || !old_no_help) {
3557 UNSET(MORE_SPACE);
3558 UNSET(NO_HELP);
3559 window_init();
3560 }
3561
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003562 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003563 nodelay(edit, FALSE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003564
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003565 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003566}
Benno Schulenbergd17438b2014-04-03 20:57:44 +00003567#endif /* !DISABLE_EXTRA */