blob: 8525fb5f74d59c857e85c9d130297b101a1da230 [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) {
Benno Schulenberg52e35332014-05-16 11:03:04 +0000126 if ((input = wgetch(win)) == ERR)
Benno Schulenberg26de2dd2014-06-27 20:01:27 +0000127 return;
Chris Allegretta0dc26dc2009-01-24 22:40:41 +0000128 } 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
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000227 * beforehand. If metakey is TRUE, put back the Escape character after
228 * putting back kbinput. If funckey is TRUE, put back the function key
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000229 * (a value outside byte range) without putting it in byte range. */
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000230void unget_kbinput(int kbinput, bool metakey, bool funckey)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000231{
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000232 if (!funckey)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000233 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
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000237 if (metakey) {
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
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000301 * sequences, and/or extended keypad values. Supported extended keypad
302 * values consist of
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000303 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
304 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
305 * the function keypad (F1-F16), and the numeric keypad with NumLock
Benno Schulenbergf876ee12014-04-15 11:25:29 +0000306 * off. */
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000307int get_kbinput(WINDOW *win)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000308{
309 int kbinput;
310
311 /* Read in a character and interpret it. Continue doing this until
312 * we get a recognized value or sequence. */
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000313 while ((kbinput = parse_kbinput(win)) == ERR)
Benno Schulenberg71c9a522014-05-13 20:14:01 +0000314 ;
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. */
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000328int parse_kbinput(WINDOW *win)
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
Benno Schulenberg7e5324d2014-06-30 18:04:33 +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
Benno Schulenberg71c9a522014-05-13 20:14:01 +0000342 while ((kbinput = get_input(win, 1)) == NULL)
343 ;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000344
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000345 switch (*kbinput) {
346 case ERR:
347 break;
348 case NANO_CONTROL_3:
349 /* Increment the escape counter. */
350 escapes++;
351 switch (escapes) {
352 case 1:
353 /* One escape: wait for more input. */
354 case 2:
355 /* Two escapes: wait for more input. */
David Lawrence Ramseyf28ff9d2006-07-24 18:53:54 +0000356 case 3:
357 /* Three escapes: wait for more input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000358 break;
359 default:
David Lawrence Ramseyf28ff9d2006-07-24 18:53:54 +0000360 /* More than three escapes: limit the escape counter
361 * to no more than two, and wait for more input. */
362 escapes %= 3;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000363 }
364 break;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000365 default:
366 switch (escapes) {
367 case 0:
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000368 /* One non-escape: normal input mode. Save the
369 * non-escape character as the result. */
370 retval = *kbinput;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000371 break;
372 case 1:
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000373 /* Reset the escape counter. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000374 escapes = 0;
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000375 if (get_key_buffer_len() == 0) {
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000376 /* One escape followed by a non-escape, and
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000377 * there aren't any other keystrokes waiting:
378 * meta key sequence mode. Set meta_key to
379 * TRUE, and save the lowercase version of the
380 * non-escape character as the result. */
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000381 meta_key = TRUE;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000382 retval = tolower(*kbinput);
David Lawrence Ramsey722b7282006-07-24 21:22:49 +0000383 } else
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000384 /* One escape followed by a non-escape, and
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000385 * there are other keystrokes waiting: escape
386 * sequence mode. Interpret the escape
387 * sequence. */
David Lawrence Ramsey5370b0c2006-07-23 17:54:35 +0000388 retval = parse_escape_seq_kbinput(win,
389 *kbinput);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000390 break;
391 case 2:
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000392 if (get_key_buffer_len() == 0) {
393 if (('0' <= *kbinput && *kbinput <= '2' &&
394 byte_digits == 0) || ('0' <= *kbinput &&
395 *kbinput <= '9' && byte_digits > 0)) {
396 /* Two escapes followed by one or more
397 * decimal digits, and there aren't any
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000398 * other keystrokes waiting: byte sequence
399 * mode. If the byte sequence's range is
400 * limited to 2XX (the first digit is in the
401 * '0' to '2' range and it's the first
402 * digit, or it's in the '0' to '9' range
403 * and it's not the first digit), increment
404 * the byte sequence counter and interpret
405 * the digit. If the byte sequence's range
406 * is not limited to 2XX, fall through. */
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000407 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000408
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000409 byte_digits++;
410 byte = get_byte_kbinput(*kbinput);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000411
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000412 if (byte != ERR) {
413 char *byte_mb;
414 int byte_mb_len, *seq, i;
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000415
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000416 /* If we've read in a complete byte
417 * sequence, reset the escape counter
418 * and the byte sequence counter, and
419 * put back the corresponding byte
420 * value. */
421 escapes = 0;
422 byte_digits = 0;
423
424 /* Put back the multibyte equivalent of
425 * the byte value. */
426 byte_mb = make_mbchar((long)byte,
427 &byte_mb_len);
428
429 seq = (int *)nmalloc(byte_mb_len *
430 sizeof(int));
431
432 for (i = 0; i < byte_mb_len; i++)
433 seq[i] = (unsigned char)byte_mb[i];
434
435 unget_input(seq, byte_mb_len);
436
437 free(byte_mb);
438 free(seq);
439 }
440 } else {
441 /* Reset the escape counter. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000442 escapes = 0;
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000443 if (byte_digits == 0)
444 /* Two escapes followed by a non-decimal
445 * digit or a decimal digit that would
446 * create a byte sequence greater than
447 * 2XX, we're not in the middle of a
448 * byte sequence, and there aren't any
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000449 * other keystrokes waiting: control
450 * character sequence mode. Interpret
451 * the control sequence and save the
452 * corresponding control character as
453 * the result. */
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000454 retval = get_control_kbinput(*kbinput);
455 else {
456 /* If we're in the middle of a byte
457 * sequence, reset the byte sequence
458 * counter and save the character we got
459 * as the result. */
460 byte_digits = 0;
461 retval = *kbinput;
462 }
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000463 }
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000464 } else {
David Lawrence Ramseya44ca782006-07-23 16:00:03 +0000465 /* Two escapes followed by a non-escape, and
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000466 * there are other keystrokes waiting: combined
467 * meta and escape sequence mode. Reset the
468 * escape counter, set meta_key to TRUE, and
469 * interpret the escape sequence. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000470 escapes = 0;
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000471 meta_key = TRUE;
David Lawrence Ramsey5370b0c2006-07-23 17:54:35 +0000472 retval = parse_escape_seq_kbinput(win,
473 *kbinput);
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000474 }
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000475 break;
David Lawrence Ramseyf28ff9d2006-07-24 18:53:54 +0000476 case 3:
477 /* Reset the escape counter. */
478 escapes = 0;
479 if (get_key_buffer_len() == 0)
480 /* Three escapes followed by a non-escape, and
481 * there aren't any other keystrokes waiting:
482 * normal input mode. Save the non-escape
483 * character as the result. */
484 retval = *kbinput;
485 else
486 /* Three escapes followed by a non-escape, and
487 * there are other keystrokes waiting: combined
488 * control character and escape sequence mode.
489 * Interpret the escape sequence, and interpret
490 * the result as a control sequence. */
491 retval = get_control_kbinput(
492 parse_escape_seq_kbinput(win,
493 *kbinput));
David Lawrence Ramsey916c7c22006-12-02 17:17:09 +0000494 break;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000495 }
496 }
497
David Lawrence Ramsey5f274c42006-04-28 19:27:41 +0000498 if (retval != ERR) {
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000499 switch (retval) {
500 case NANO_CONTROL_8:
Chris Allegretta637daa82011-02-07 14:45:56 +0000501 retval = ISSET(REBIND_DELETE) ? sc_seq_or(do_delete, 0) :
502 sc_seq_or(do_backspace, 0);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000503 break;
504 case KEY_DOWN:
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000505#ifdef KEY_SDOWN
506 /* ncurses and Slang don't support KEY_SDOWN. */
507 case KEY_SDOWN:
508#endif
Chris Allegretta637daa82011-02-07 14:45:56 +0000509 retval = sc_seq_or(do_down_void, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000510 break;
511 case KEY_UP:
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000512#ifdef KEY_SUP
513 /* ncurses and Slang don't support KEY_SUP. */
514 case KEY_SUP:
515#endif
Chris Allegretta637daa82011-02-07 14:45:56 +0000516 retval = sc_seq_or(do_up_void, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000517 break;
518 case KEY_LEFT:
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000519#ifdef KEY_SLEFT
520 /* Slang doesn't support KEY_SLEFT. */
521 case KEY_SLEFT:
522#endif
Chris Allegretta637daa82011-02-07 14:45:56 +0000523 retval = sc_seq_or(do_left, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000524 break;
525 case KEY_RIGHT:
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000526#ifdef KEY_SRIGHT
527 /* Slang doesn't support KEY_SRIGHT. */
528 case KEY_SRIGHT:
529#endif
Chris Allegretta637daa82011-02-07 14:45:56 +0000530 retval = sc_seq_or(do_right, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000531 break;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000532#ifdef KEY_SHOME
533 /* HP-UX 10-11 and Slang don't support KEY_SHOME. */
534 case KEY_SHOME:
535#endif
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000536 case KEY_A1: /* Home (7) on numeric keypad with
537 * NumLock off. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000538 retval = sc_seq_or(do_home, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000539 break;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000540 case KEY_BACKSPACE:
Chris Allegretta637daa82011-02-07 14:45:56 +0000541 retval = sc_seq_or(do_backspace, *kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000542 break;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000543#ifdef KEY_SDC
544 /* Slang doesn't support KEY_SDC. */
545 case KEY_SDC:
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000546 if (ISSET(REBIND_DELETE))
Benno Schulenberga8a23ab2014-06-10 19:12:14 +0000547 retval = sc_seq_or(do_delete, *kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000548 else
Benno Schulenberga8a23ab2014-06-10 19:12:14 +0000549 retval = sc_seq_or(do_backspace, *kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000550 break;
Chris Allegretta17436ce2008-03-11 03:03:53 +0000551#endif
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000552#ifdef KEY_SIC
553 /* Slang doesn't support KEY_SIC. */
554 case KEY_SIC:
Chris Allegretta637daa82011-02-07 14:45:56 +0000555 retval = sc_seq_or(do_insertfile_void, *kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000556 break;
Chris Allegretta17436ce2008-03-11 03:03:53 +0000557#endif
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000558 case KEY_C3: /* PageDown (4) on numeric keypad with
559 * NumLock off. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000560 retval = sc_seq_or(do_page_down, *kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000561 break;
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000562 case KEY_A3: /* PageUp (9) on numeric keypad with
563 * NumLock off. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000564 retval = sc_seq_or(do_page_up, *kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000565 break;
566 case KEY_ENTER:
Chris Allegretta637daa82011-02-07 14:45:56 +0000567 retval = sc_seq_or(do_enter_void, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000568 break;
569 case KEY_B2: /* Center (5) on numeric keypad with
570 * NumLock off. */
571 retval = ERR;
572 break;
573 case KEY_C1: /* End (1) on numeric keypad with
574 * NumLock off. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000575#ifdef KEY_SEND
576 /* HP-UX 10-11 and Slang don't support KEY_SEND. */
577 case KEY_SEND:
578#endif
Chris Allegretta637daa82011-02-07 14:45:56 +0000579 retval = sc_seq_or(do_end, *kbinput);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000580 break;
581#ifdef KEY_BEG
582 /* Slang doesn't support KEY_BEG. */
583 case KEY_BEG: /* Center (5) on numeric keypad with
584 * NumLock off. */
585 retval = ERR;
586 break;
587#endif
David Lawrence Ramsey6a8b3502007-04-18 14:06:34 +0000588#ifdef KEY_CANCEL
589 /* Slang doesn't support KEY_CANCEL. */
590 case KEY_CANCEL:
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000591#ifdef KEY_SCANCEL
592 /* Slang doesn't support KEY_SCANCEL. */
593 case KEY_SCANCEL:
David Lawrence Ramsey6a8b3502007-04-18 14:06:34 +0000594#endif
Chris Allegretta637daa82011-02-07 14:45:56 +0000595 retval = first_sc_for(currmenu, do_cancel)->seq;
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000596 break;
597#endif
598#ifdef KEY_SBEG
599 /* Slang doesn't support KEY_SBEG. */
600 case KEY_SBEG: /* Center (5) on numeric keypad with
601 * NumLock off. */
602 retval = ERR;
603 break;
604#endif
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000605#ifdef KEY_SSUSPEND
606 /* Slang doesn't support KEY_SSUSPEND. */
607 case KEY_SSUSPEND:
Chris Allegretta637daa82011-02-07 14:45:56 +0000608 retval = sc_seq_or(do_suspend_void, 0);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000609 break;
610#endif
611#ifdef KEY_SUSPEND
612 /* Slang doesn't support KEY_SUSPEND. */
613 case KEY_SUSPEND:
Benno Schulenberg52e35332014-05-16 11:03:04 +0000614 retval = sc_seq_or(do_suspend_void, 0);
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000615 break;
616#endif
617#ifdef PDCURSES
618 case KEY_SHIFT_L:
619 case KEY_SHIFT_R:
620 case KEY_CONTROL_L:
621 case KEY_CONTROL_R:
622 case KEY_ALT_L:
623 case KEY_ALT_R:
624 retval = ERR;
625 break;
626#endif
627#if !defined(NANO_TINY) && defined(KEY_RESIZE)
628 /* Since we don't change the default SIGWINCH handler when
629 * NANO_TINY is defined, KEY_RESIZE is never generated.
630 * Also, Slang and SunOS 5.7-5.9 don't support
631 * KEY_RESIZE. */
632 case KEY_RESIZE:
633 retval = ERR;
634 break;
635#endif
Benno Schulenberg09dd0a42014-06-29 20:53:00 +0000636 case CONTROL_LEFT:
637#ifndef NANO_TINY
638 retval = sc_seq_or(do_prev_word_void, 0);
639#endif
640 break;
641 case CONTROL_RIGHT:
642#ifndef NANO_TINY
643 retval = sc_seq_or(do_next_word_void, 0);
644#endif
645 break;
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000646 }
David Lawrence Ramsey5f274c42006-04-28 19:27:41 +0000647
David Lawrence Ramseyb159f942006-07-28 17:06:27 +0000648 /* If our result is an extended keypad value (i.e. a value
David Lawrence Ramsey5f274c42006-04-28 19:27:41 +0000649 * outside of byte range), set func_key to TRUE. */
David Lawrence Ramsey19f3bd62006-07-23 17:25:38 +0000650 if (retval != ERR)
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000651 func_key = !is_byte(retval);
David Lawrence Ramsey5f274c42006-04-28 19:27:41 +0000652 }
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000653
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000654#ifdef DEBUG
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000655 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 +0000656#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000657
David Lawrence Ramseyad36bdc2006-12-02 17:22:21 +0000658 free(kbinput);
659
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000660 /* Return the result. */
661 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000662}
663
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000664/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000665 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +0000666 * are generated when the keypad doesn't support the needed keys.
667 * Assume that Escape has already been read in. */
668int get_escape_seq_kbinput(const int *seq, size_t seq_len)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000669{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000670 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000671
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000672 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000673 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000674 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000675 switch (seq[1]) {
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000676 case '1':
677 if (seq_len >= 3) {
678 switch (seq[2]) {
679 case ';':
680 if (seq_len >= 4) {
681 switch (seq[3]) {
682 case '2':
683 if (seq_len >= 5) {
684 switch (seq[4]) {
685 case 'A': /* Esc O 1 ; 2 A == Shift-Up on
686 * Terminal. */
687 case 'B': /* Esc O 1 ; 2 B == Shift-Down on
688 * Terminal. */
689 case 'C': /* Esc O 1 ; 2 C == Shift-Right on
690 * Terminal. */
691 case 'D': /* Esc O 1 ; 2 D == Shift-Left on
692 * Terminal. */
693 retval = get_escape_seq_abcd(seq[4]);
694 break;
695 case 'P': /* Esc O 1 ; 2 P == F13 on
696 * Terminal. */
697 retval = KEY_F(13);
698 break;
699 case 'Q': /* Esc O 1 ; 2 Q == F14 on
700 * Terminal. */
701 retval = KEY_F(14);
702 break;
703 case 'R': /* Esc O 1 ; 2 R == F15 on
704 * Terminal. */
705 retval = KEY_F(15);
706 break;
707 case 'S': /* Esc O 1 ; 2 S == F16 on
708 * Terminal. */
709 retval = KEY_F(16);
710 break;
711 }
712 }
713 break;
714 case '5':
715 if (seq_len >= 5) {
716 switch (seq[4]) {
717 case 'A': /* Esc O 1 ; 5 A == Ctrl-Up on
718 * Terminal. */
719 case 'B': /* Esc O 1 ; 5 B == Ctrl-Down on
720 * Terminal. */
Benno Schulenberg09dd0a42014-06-29 20:53:00 +0000721 retval = get_escape_seq_abcd(seq[4]);
722 break;
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000723 case 'C': /* Esc O 1 ; 5 C == Ctrl-Right on
724 * Terminal. */
Benno Schulenberg09dd0a42014-06-29 20:53:00 +0000725 retval = CONTROL_RIGHT;
726 break;
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000727 case 'D': /* Esc O 1 ; 5 D == Ctrl-Left on
728 * Terminal. */
Benno Schulenberg09dd0a42014-06-29 20:53:00 +0000729 retval = CONTROL_LEFT;
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000730 break;
731 }
732 }
733 break;
734 }
735 }
736 break;
737 }
738 }
739 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000740 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000741 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000742 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000743 case 'P': /* Esc O 2 P == F13 on
744 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000745 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000746 break;
747 case 'Q': /* Esc O 2 Q == F14 on
748 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000749 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000750 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000751 case 'R': /* Esc O 2 R == F15 on
752 * xterm. */
753 retval = KEY_F(15);
754 break;
755 case 'S': /* Esc O 2 S == F16 on
756 * xterm. */
757 retval = KEY_F(16);
758 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000759 }
760 }
761 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000762 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
763 case 'B': /* Esc O B == Down on
764 * VT100/VT320/xterm. */
765 case 'C': /* Esc O C == Right on
766 * VT100/VT320/xterm. */
767 case 'D': /* Esc O D == Left on
768 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000769 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000770 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000771 case 'E': /* Esc O E == Center (5) on numeric keypad
772 * with NumLock off on xterm. */
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +0000773 retval = KEY_B2;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000774 break;
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000775 case 'F': /* Esc O F == End on xterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000776 retval = sc_seq_or(do_end, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000777 break;
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000778 case 'H': /* Esc O H == Home on xterm/Terminal. */
Benno Schulenberg25e58962014-04-23 19:33:03 +0000779 retval = sc_seq_or(do_home, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000780 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000781 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000782 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000783 * rxvt/Eterm. */
Benno Schulenberg25e58962014-04-23 19:33:03 +0000784 retval = sc_seq_or(do_home, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000785 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000786 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000787 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000788 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000789 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000790 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000791 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000792 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000793 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000794 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000795 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000796 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000797 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000798 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000799 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000800 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000801 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000802 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000803 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000804 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000805 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000806 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000807 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000808 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000809 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000810 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000811 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000812 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000813 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000814 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000815 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000816 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000817 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000818 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000819 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000820 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000821 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000822 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000823 break;
Benno Schulenberg09dd0a42014-06-29 20:53:00 +0000824 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
825 retval = CONTROL_RIGHT;
826 break;
827 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
828 retval = CONTROL_LEFT;
829 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000830 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000831 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000832 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000833 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000834 break;
835 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000836 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000837 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000838 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000839 break;
840 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000841 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000842 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey8f36d092005-09-24 19:42:48 +0000843 retval = ',';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000844 break;
845 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000846 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000847 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000848 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000849 break;
850 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000851 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000852 * xterm/rxvt/Eterm/Terminal. */
Benno Schulenberg25e58962014-04-23 19:33:03 +0000853 retval = sc_seq_or(do_delete, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000854 break;
855 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000856 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000857 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000858 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000859 break;
860 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000861 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000862 * rxvt/Eterm/Terminal. */
Benno Schulenberg25e58962014-04-23 19:33:03 +0000863 retval = sc_seq_or(do_insertfile_void, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000864 break;
865 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000866 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000867 * rxvt/Eterm/Terminal. */
Benno Schulenberg25e58962014-04-23 19:33:03 +0000868 retval = sc_seq_or(do_end, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000869 break;
870 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000871 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000872 * rxvt/Eterm/Terminal. */
Benno Schulenberg25e58962014-04-23 19:33:03 +0000873 retval = sc_seq_or(do_down_void, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000874 break;
875 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000876 * keypad with NumLock off on VT100/VT220/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000877 * VT320/rxvt/Eterm/Terminal. */
Benno Schulenberg25e58962014-04-23 19:33:03 +0000878 retval = sc_seq_or(do_page_down, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000879 break;
880 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000881 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000882 * rxvt/Eterm/Terminal. */
Benno Schulenberg25e58962014-04-23 19:33:03 +0000883 retval = sc_seq_or(do_left, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000884 break;
885 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000886 * with NumLock off on VT100/VT220/VT320/
887 * rxvt/Eterm. */
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +0000888 retval = KEY_B2;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000889 break;
890 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000891 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000892 * rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000893 retval = sc_seq_or(do_right, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000894 break;
895 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000896 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000897 * rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000898 retval = sc_seq_or(do_home, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000899 break;
900 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000901 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000902 * rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000903 retval = sc_seq_or(do_up_void, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000904 break;
905 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000906 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +0000907 * rxvt/Eterm/Terminal. */
Chris Allegretta637daa82011-02-07 14:45:56 +0000908 retval = sc_seq_or(do_page_up, 0);
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000909 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000910 }
911 break;
912 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000913 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000914 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000915 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000916 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000917 break;
Benno Schulenberg09dd0a42014-06-29 20:53:00 +0000918 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
919 retval = CONTROL_RIGHT;
920 break;
921 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
922 retval = CONTROL_LEFT;
923 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000924 }
925 break;
926 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000927 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000928 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000929 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000930 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000931 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
932 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000933 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000934 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000935 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
936 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000937 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000938 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000939 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
940 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000941 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000942 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000943 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
944 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000945 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000946 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000947 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
948 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000949 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000950 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000951 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000952 * VT220/VT320/Linux console/
953 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000954 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000955 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000956 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000957 * VT220/VT320/Linux console/
958 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000959 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000960 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000961 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000962 * VT220/VT320/Linux console/
963 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000964 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000965 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000966 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000967 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000968 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000969 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000970 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000971 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000972 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
973 * xterm. */
974 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
975 * xterm. */
976 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
977 * xterm. */
978 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
979 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000980 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000981 break;
982 }
983 }
984 break;
985 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000986 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000987 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000988 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
989 * xterm. */
990 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
991 * xterm. */
Benno Schulenberg09dd0a42014-06-29 20:53:00 +0000992 retval = get_escape_seq_abcd(seq[4]);
993 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000994 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
995 * xterm. */
Benno Schulenberg09dd0a42014-06-29 20:53:00 +0000996 retval = CONTROL_RIGHT;
997 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000998 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
999 * xterm. */
Benno Schulenberg09dd0a42014-06-29 20:53:00 +00001000 retval = CONTROL_LEFT;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +00001001 break;
1002 }
1003 }
1004 break;
1005 }
1006 }
1007 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001008 default: /* Esc [ 1 ~ == Home on
1009 * VT320/Linux console. */
Benno Schulenberg25e58962014-04-23 19:33:03 +00001010 retval = sc_seq_or(do_home, 0);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001011 break;
1012 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001013 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001014 break;
1015 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001016 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001017 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001018 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001019 * VT220/VT320/Linux console/
1020 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001021 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001022 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001023 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001024 * VT220/VT320/Linux console/
1025 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001026 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001027 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001028 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001029 * VT220/VT320/Linux console/
1030 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001031 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001032 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001033 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001034 * VT220/VT320/Linux console/
1035 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001036 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001037 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001038 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001039 * VT220/VT320/Linux console/
1040 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001041 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001042 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001043 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001044 * VT220/VT320/Linux console/
1045 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001046 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001047 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +00001048 case '8': /* Esc [ 2 8 ~ == F15 on
1049 * VT220/VT320/Linux console/
1050 * rxvt/Eterm. */
1051 retval = KEY_F(15);
1052 break;
1053 case '9': /* Esc [ 2 9 ~ == F16 on
1054 * VT220/VT320/Linux console/
1055 * rxvt/Eterm. */
1056 retval = KEY_F(16);
1057 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001058 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001059 * VT220/VT320/Linux console/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +00001060 * xterm/Terminal. */
Benno Schulenberg25e58962014-04-23 19:33:03 +00001061 retval = sc_seq_or(do_insertfile_void, 0);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001062 break;
1063 }
1064 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001065 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001066 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +00001067 * Linux console/xterm/Terminal. */
Benno Schulenberg25e58962014-04-23 19:33:03 +00001068 retval = sc_seq_or(do_delete, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001069 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001070 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001071 * console/xterm. */
Benno Schulenberg25e58962014-04-23 19:33:03 +00001072 retval = sc_seq_or(do_end, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001073 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001074 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +00001075 * Linux console/xterm/Terminal;
1076 * Esc [ 5 ^ == PageUp on Eterm. */
Benno Schulenberg25e58962014-04-23 19:33:03 +00001077 retval = sc_seq_or(do_page_up, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001078 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001079 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +00001080 * Linux console/xterm/Terminal;
Benno Schulenberg1de337d2014-06-04 16:02:51 +00001081 * Esc [ 6 ^ == PageDown on Eterm. */
Benno Schulenberg25e58962014-04-23 19:33:03 +00001082 retval = sc_seq_or(do_page_down, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001083 break;
1084 case '7': /* Esc [ 7 ~ == Home on rxvt. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001085 retval = sc_seq_or(do_home, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001086 break;
1087 case '8': /* Esc [ 8 ~ == End on rxvt. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001088 retval = sc_seq_or(do_end, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001089 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001090 case '9': /* Esc [ 9 == Delete on Mach console. */
Benno Schulenberg25e58962014-04-23 19:33:03 +00001091 retval = sc_seq_or(do_delete, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001092 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001093 case '@': /* Esc [ @ == Insert on Mach console. */
Benno Schulenberg25e58962014-04-23 19:33:03 +00001094 retval = sc_seq_or(do_insertfile_void, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001095 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001096 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001097 * console/FreeBSD console/Mach console/
David Lawrence Ramseya31d54e2007-04-18 13:48:37 +00001098 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001099 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001100 * console/FreeBSD console/Mach console/
David Lawrence Ramseya31d54e2007-04-18 13:48:37 +00001101 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001102 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001103 * console/FreeBSD console/Mach console/
David Lawrence Ramseya31d54e2007-04-18 13:48:37 +00001104 * rxvt/Eterm/Terminal. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001105 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001106 * console/FreeBSD console/Mach console/
David Lawrence Ramseya31d54e2007-04-18 13:48:37 +00001107 * rxvt/Eterm/Terminal. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001108 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001109 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001110 case 'E': /* Esc [ E == Center (5) on numeric keypad
David Lawrence Ramsey267daeb2007-04-04 20:36:56 +00001111 * with NumLock off on FreeBSD console/
1112 * Terminal. */
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +00001113 retval = KEY_B2;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001114 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001115 case 'F': /* Esc [ F == End on FreeBSD
1116 * console/Eterm. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001117 retval = sc_seq_or(do_end, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001118 break;
1119 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001120 * console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001121 retval = sc_seq_or(do_page_down, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001122 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001123 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001124 * console/Mach console/Eterm. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001125 retval = sc_seq_or(do_home, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001126 break;
1127 case 'I': /* Esc [ I == PageUp on FreeBSD
1128 * console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001129 retval = sc_seq_or(do_page_up, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001130 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001131 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001132 * console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001133 retval = sc_seq_or(do_insertfile_void, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001134 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001135 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001136 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001137 break;
1138 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001139 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001140 break;
1141 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001142 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001143 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001144 case 'P': /* Esc [ O P == F1 on
1145 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001146 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001147 break;
1148 case 'Q': /* Esc [ O Q == F2 on
1149 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001150 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001151 break;
1152 case 'R': /* Esc [ O R == F3 on
1153 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001154 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001155 break;
1156 case 'S': /* Esc [ O S == F4 on
1157 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001158 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001159 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001160 }
David Lawrence Ramseyec729752005-09-25 18:42:05 +00001161 } else
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001162 /* Esc [ O == F3 on FreeBSD console. */
1163 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001164 break;
1165 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001166 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001167 break;
1168 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001169 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001170 break;
1171 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001172 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001173 break;
1174 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001175 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001176 break;
1177 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001178 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001179 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001180 case 'U': /* Esc [ U == PageDown on Mach console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001181 retval = sc_seq_or(do_page_down, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001182 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001183 case 'V': /* Esc [ V == PageUp on Mach console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001184 retval = sc_seq_or(do_page_up, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001185 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001186 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001187 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001188 break;
1189 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001190 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001191 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001192 case 'Y': /* Esc [ Y == End on Mach console. */
Chris Allegretta637daa82011-02-07 14:45:56 +00001193 retval = sc_seq_or(do_end, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001194 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001195 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001196 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001197 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001198 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001199 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001200 case 'c': /* Esc [ c == Shift-Right on rxvt/
1201 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001202 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001203 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001204 break;
1205 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001206 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001207 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001208 case 'A': /* Esc [ [ A == F1 on Linux
1209 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001210 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001211 break;
1212 case 'B': /* Esc [ [ B == F2 on Linux
1213 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001214 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001215 break;
1216 case 'C': /* Esc [ [ C == F3 on Linux
1217 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001218 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001219 break;
1220 case 'D': /* Esc [ [ D == F4 on Linux
1221 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001222 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001223 break;
1224 case 'E': /* Esc [ [ E == F5 on Linux
1225 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001226 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001227 break;
1228 }
1229 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001230 break;
1231 }
1232 break;
1233 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001234 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001235
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001236#ifdef DEBUG
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +00001237 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d\n", retval);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001238#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001239
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001240 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001241}
1242
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001243/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001244 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001245 * to many escape sequences. */
1246int get_escape_seq_abcd(int kbinput)
1247{
1248 switch (tolower(kbinput)) {
1249 case 'a':
Benno Schulenberg25e58962014-04-23 19:33:03 +00001250 return sc_seq_or(do_up_void, 0);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001251 case 'b':
Benno Schulenberg25e58962014-04-23 19:33:03 +00001252 return sc_seq_or(do_down_void, 0);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001253 case 'c':
Benno Schulenberg25e58962014-04-23 19:33:03 +00001254 return sc_seq_or(do_right, 0);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001255 case 'd':
Benno Schulenberg25e58962014-04-23 19:33:03 +00001256 return sc_seq_or(do_left, 0);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001257 default:
1258 return ERR;
1259 }
1260}
1261
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001262/* Interpret the escape sequence in the keystroke buffer, the first
David Lawrence Ramsey5370b0c2006-07-23 17:54:35 +00001263 * character of which is kbinput. Assume that the keystroke buffer
1264 * isn't empty, and that the initial escape has already been read in. */
1265int parse_escape_seq_kbinput(WINDOW *win, int kbinput)
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001266{
1267 int retval, *seq;
1268 size_t seq_len;
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001269
1270 /* Put back the non-escape character, get the complete escape
1271 * sequence, translate the sequence into its corresponding key
1272 * value, and save that as the result. */
1273 unget_input(&kbinput, 1);
1274 seq_len = get_key_buffer_len();
1275 seq = get_input(NULL, seq_len);
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +00001276 retval = get_escape_seq_kbinput(seq, seq_len);
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001277
1278 free(seq);
1279
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +00001280 /* If we got an unrecognized escape sequence, throw it out. */
1281 if (retval == ERR) {
David Lawrence Ramsey8a723702006-07-23 18:00:50 +00001282 if (win == edit) {
David Lawrence Ramsey5370b0c2006-07-23 17:54:35 +00001283 statusbar(_("Unknown Command"));
1284 beep();
1285 }
1286 }
1287
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001288#ifdef DEBUG
David Lawrence Ramsey1b4ae692006-07-25 19:23:35 +00001289 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 +00001290#endif
1291
1292 return retval;
1293}
1294
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001295/* Translate a byte sequence: turn a three-digit decimal number (from
1296 * 000 to 255) into its corresponding byte value. */
David Lawrence Ramseyfc0f8f82006-05-10 13:41:53 +00001297int get_byte_kbinput(int kbinput)
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001298{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001299 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001300 int retval = ERR;
1301
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001302 /* Increment the byte digit counter. */
1303 byte_digits++;
1304
1305 switch (byte_digits) {
1306 case 1:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001307 /* First digit: This must be from zero to two. Put it in
1308 * the 100's position of the byte sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001309 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001310 byte = (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001311 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001312 /* This isn't the start of a byte sequence. Return this
1313 * character as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001314 retval = kbinput;
1315 break;
1316 case 2:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001317 /* Second digit: This must be from zero to five if the first
1318 * was two, and may be any decimal value if the first was
1319 * zero or one. Put it in the 10's position of the byte
1320 * sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001321 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1322 '6' <= kbinput && kbinput <= '9'))
1323 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001324 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001325 /* This isn't the second digit of a byte sequence.
1326 * Return this character as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001327 retval = kbinput;
1328 break;
1329 case 3:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001330 /* Third digit: This must be from zero to five if the first
Benno Schulenbergf876ee12014-04-15 11:25:29 +00001331 * was two and the second was five, and may be any decimal
1332 * value otherwise. Put it in the 1's position of the byte
1333 * sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001334 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1335 '6' <= kbinput && kbinput <= '9')) {
David Lawrence Ramsey28889642006-05-30 20:51:15 +00001336 byte += kbinput - '0';
Benno Schulenbergf876ee12014-04-15 11:25:29 +00001337 /* The byte sequence is complete. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001338 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001339 } else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001340 /* This isn't the third digit of a byte sequence.
1341 * Return this character as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001342 retval = kbinput;
1343 break;
1344 default:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001345 /* If there are more than three digits, return this
1346 * character as the result. (Maybe we should produce an
1347 * error instead?) */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001348 retval = kbinput;
1349 break;
1350 }
1351
1352 /* If we have a result, reset the byte digit counter and the byte
1353 * sequence holder. */
1354 if (retval != ERR) {
1355 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001356 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001357 }
1358
1359#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001360 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 +00001361#endif
1362
1363 return retval;
1364}
1365
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001366#ifdef ENABLE_UTF8
David Lawrence Ramsey7f1b1192006-05-28 17:30:28 +00001367/* If the character in kbinput is a valid hexadecimal digit, multiply it
1368 * by factor and add the result to uni. */
1369long add_unicode_digit(int kbinput, long factor, long *uni)
1370{
1371 long retval = ERR;
1372
1373 if ('0' <= kbinput && kbinput <= '9')
1374 *uni += (kbinput - '0') * factor;
1375 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
1376 *uni += (tolower(kbinput) - 'a' + 10) * factor;
1377 else
1378 /* If this character isn't a valid hexadecimal value, save it as
1379 * the result. */
1380 retval = kbinput;
1381
1382 return retval;
1383}
1384
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001385/* Translate a Unicode sequence: turn a six-digit hexadecimal number
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001386 * (from 000000 to 10FFFF, case-insensitive) into its corresponding
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001387 * multibyte value. */
David Lawrence Ramseyfc0f8f82006-05-10 13:41:53 +00001388long get_unicode_kbinput(int kbinput)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001389{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001390 static int uni_digits = 0;
1391 static long uni = 0;
1392 long retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001393
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001394 /* Increment the Unicode digit counter. */
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001395 uni_digits++;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001396
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001397 switch (uni_digits) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001398 case 1:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001399 /* First digit: This must be zero or one. Put it in the
1400 * 0x100000's position of the Unicode sequence holder. */
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001401 if ('0' <= kbinput && kbinput <= '1')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001402 uni = (kbinput - '0') * 0x100000;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001403 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001404 /* This isn't the first digit of a Unicode sequence.
1405 * Return this character as the result. */
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001406 retval = kbinput;
1407 break;
1408 case 2:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001409 /* Second digit: This must be zero if the first was one, and
1410 * may be any hexadecimal value if the first was zero. Put
1411 * it in the 0x10000's position of the Unicode sequence
1412 * holder. */
1413 if (uni == 0 || '0' == kbinput)
1414 retval = add_unicode_digit(kbinput, 0x10000, &uni);
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001415 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001416 /* This isn't the second digit of a Unicode sequence.
1417 * Return this character as the result. */
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001418 retval = kbinput;
1419 break;
1420 case 3:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001421 /* Third digit: This may be any hexadecimal value. Put it
1422 * in the 0x1000's position of the Unicode sequence
1423 * holder. */
1424 retval = add_unicode_digit(kbinput, 0x1000, &uni);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001425 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001426 case 4:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001427 /* Fourth digit: This may be any hexadecimal value. Put it
1428 * in the 0x100's position of the Unicode sequence
1429 * holder. */
1430 retval = add_unicode_digit(kbinput, 0x100, &uni);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001431 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001432 case 5:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001433 /* Fifth digit: This may be any hexadecimal value. Put it
1434 * in the 0x10's position of the Unicode sequence holder. */
1435 retval = add_unicode_digit(kbinput, 0x10, &uni);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001436 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001437 case 6:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001438 /* Sixth digit: This may be any hexadecimal value. Put it
1439 * in the 0x1's position of the Unicode sequence holder. */
1440 retval = add_unicode_digit(kbinput, 0x1, &uni);
1441 /* If this character is a valid hexadecimal value, then the
1442 * Unicode sequence is complete. */
1443 if (retval == ERR)
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001444 retval = uni;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001445 break;
1446 default:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001447 /* If there are more than six digits, return this character
1448 * as the result. (Maybe we should produce an error
1449 * instead?) */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001450 retval = kbinput;
1451 break;
1452 }
1453
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001454 /* If we have a result, reset the Unicode digit counter and the
1455 * Unicode sequence holder. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001456 if (retval != ERR) {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001457 uni_digits = 0;
1458 uni = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001459 }
1460
1461#ifdef DEBUG
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001462 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 +00001463#endif
1464
1465 return retval;
1466}
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001467#endif /* ENABLE_UTF8 */
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001468
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001469/* Translate a control character sequence: turn an ASCII non-control
1470 * character into its corresponding control character. */
1471int get_control_kbinput(int kbinput)
1472{
1473 int retval;
1474
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001475 /* Ctrl-Space (Ctrl-2, Ctrl-@, Ctrl-`) */
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001476 if (kbinput == ' ' || kbinput == '2')
1477 retval = NANO_CONTROL_SPACE;
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001478 /* Ctrl-/ (Ctrl-7, Ctrl-_) */
1479 else if (kbinput == '/')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001480 retval = NANO_CONTROL_7;
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001481 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-/, Ctrl-_) */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001482 else if ('3' <= kbinput && kbinput <= '7')
1483 retval = kbinput - 24;
1484 /* Ctrl-8 (Ctrl-?) */
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001485 else if (kbinput == '8' || kbinput == '?')
1486 retval = NANO_CONTROL_8;
David Lawrence Ramsey51cb7fd2006-05-20 17:19:09 +00001487 /* Ctrl-@ (Ctrl-Space, Ctrl-2, Ctrl-`) to Ctrl-_ (Ctrl-/, Ctrl-7) */
1488 else if ('@' <= kbinput && kbinput <= '_')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001489 retval = kbinput - '@';
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001490 /* Ctrl-` (Ctrl-2, Ctrl-Space, Ctrl-@) to Ctrl-~ (Ctrl-6, Ctrl-^) */
1491 else if ('`' <= kbinput && kbinput <= '~')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001492 retval = kbinput - '`';
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001493 else
1494 retval = kbinput;
1495
1496#ifdef DEBUG
1497 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1498#endif
1499
1500 return retval;
1501}
1502
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +00001503/* Put the output-formatted characters in output back into the keystroke
1504 * buffer, so that they can be parsed and displayed as output again. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001505void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001506{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001507 int *input;
1508 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001509
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001510 if (output_len == 0)
1511 return;
1512
1513 input = (int *)nmalloc(output_len * sizeof(int));
David Lawrence Ramseybd539802006-12-02 23:39:16 +00001514
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001515 for (i = 0; i < output_len; i++)
1516 input[i] = (int)output[i];
David Lawrence Ramseybd539802006-12-02 23:39:16 +00001517
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001518 unget_input(input, output_len);
David Lawrence Ramseybd539802006-12-02 23:39:16 +00001519
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001520 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001521}
1522
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001523/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001524 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1525int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1526{
1527 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001528
1529 /* Turn off flow control characters if necessary so that we can type
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001530 * them in verbatim, and turn the keypad off if necessary so that we
1531 * don't get extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001532 if (ISSET(PRESERVE))
1533 disable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001534 if (!ISSET(REBIND_KEYPAD))
1535 keypad(win, FALSE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001536
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001537 /* Read in a stream of characters and interpret it if possible. */
1538 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001539
1540 /* Turn flow control characters back on if necessary and turn the
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001541 * keypad back on if necessary now that we're done. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001542 if (ISSET(PRESERVE))
1543 enable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001544 if (!ISSET(REBIND_KEYPAD))
1545 keypad(win, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001546
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001547 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001548}
1549
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001550/* Read in a stream of all available characters, and return the length
1551 * of the string in kbinput_len. Translate the first few characters of
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001552 * the input into the corresponding multibyte value if possible. After
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00001553 * that, leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001554int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001555{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001556 int *kbinput, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001557
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001558 /* Read in the first keystroke. */
Benno Schulenberg71c9a522014-05-13 20:14:01 +00001559 while ((kbinput = get_input(win, 1)) == NULL)
1560 ;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001561
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001562#ifdef ENABLE_UTF8
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001563 if (using_utf8()) {
1564 /* Check whether the first keystroke is a valid hexadecimal
1565 * digit. */
David Lawrence Ramseya5b1ca22006-05-28 17:09:49 +00001566 long uni = get_unicode_kbinput(*kbinput);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001567
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001568 /* If the first keystroke isn't a valid hexadecimal digit, put
1569 * back the first keystroke. */
1570 if (uni != ERR)
1571 unget_input(kbinput, 1);
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001572
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001573 /* Otherwise, read in keystrokes until we have a complete
1574 * Unicode sequence, and put back the corresponding Unicode
1575 * value. */
1576 else {
1577 char *uni_mb;
1578 int uni_mb_len, *seq, i;
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001579
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001580 if (win == edit)
1581 /* TRANSLATORS: This is displayed during the input of a
1582 * six-digit hexadecimal Unicode character code. */
1583 statusbar(_("Unicode Input"));
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001584
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001585 while (uni == ERR) {
Benno Schulenberg71c9a522014-05-13 20:14:01 +00001586 while ((kbinput = get_input(win, 1)) == NULL)
1587 ;
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001588 uni = get_unicode_kbinput(*kbinput);
1589 }
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001590
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001591 /* Put back the multibyte equivalent of the Unicode
1592 * value. */
1593 uni_mb = make_mbchar(uni, &uni_mb_len);
1594
1595 seq = (int *)nmalloc(uni_mb_len * sizeof(int));
1596
1597 for (i = 0; i < uni_mb_len; i++)
1598 seq[i] = (unsigned char)uni_mb[i];
1599
1600 unget_input(seq, uni_mb_len);
1601
1602 free(seq);
1603 free(uni_mb);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001604 }
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001605 } else
David Lawrence Ramseya5b1ca22006-05-28 17:09:49 +00001606#endif /* ENABLE_UTF8 */
1607
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001608 /* Put back the first keystroke. */
1609 unget_input(kbinput, 1);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001610
David Lawrence Ramseyad36bdc2006-12-02 17:22:21 +00001611 free(kbinput);
1612
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001613 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001614 * result. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00001615 *kbinput_len = get_key_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001616 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001617
1618 return retval;
1619}
1620
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001621#ifndef DISABLE_MOUSE
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001622/* Handle any mouse event that may have occurred. We currently handle
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001623 * releases/clicks of the first mouse button. If allow_shortcuts is
1624 * TRUE, releasing/clicking on a visible shortcut will put back the
1625 * keystroke associated with that shortcut. If NCURSES_MOUSE_VERSION is
1626 * at least 2, we also currently handle presses of the fourth mouse
1627 * button (upward rolls of the mouse wheel) by putting back the
1628 * keystrokes to move up, and presses of the fifth mouse button
1629 * (downward rolls of the mouse wheel) by putting back the keystrokes to
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001630 * move down. We also store the coordinates of a mouse event that needs
1631 * to be handled in mouse_x and mouse_y, relative to the entire screen.
1632 * Return -1 on error, 0 if the mouse event needs to be handled, 1 if
1633 * it's been handled by putting back keystrokes that need to be handled.
1634 * or 2 if it's been ignored. Assume that KEY_MOUSE has already been
1635 * read in. */
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001636int get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001637{
1638 MEVENT mevent;
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001639 bool in_bottomwin;
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001640 subnfunc *f;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001641
1642 *mouse_x = -1;
1643 *mouse_y = -1;
1644
1645 /* First, get the actual mouse event. */
1646 if (getmouse(&mevent) == ERR)
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001647 return -1;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001648
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001649 /* Save the screen coordinates where the mouse event took place. */
1650 *mouse_x = mevent.x;
1651 *mouse_y = mevent.y;
David Lawrence Ramsey98e4d4f2006-06-28 21:54:55 +00001652
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001653 in_bottomwin = wenclose(bottomwin, *mouse_y, *mouse_x);
1654
David Lawrence Ramsey5fcf8bf2007-06-28 18:31:13 +00001655 /* Handle releases/clicks of the first mouse button. */
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001656 if (mevent.bstate & (BUTTON1_RELEASED | BUTTON1_CLICKED)) {
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001657 /* If we're allowing shortcuts, the current shortcut list is
1658 * being displayed on the last two lines of the screen, and the
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001659 * first mouse button was released on/clicked inside it, we need
1660 * to figure out which shortcut was released on/clicked and put
1661 * back the equivalent keystroke(s) for it. */
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001662 if (allow_shortcuts && !ISSET(NO_HELP) && in_bottomwin) {
David Lawrence Ramseybc653132007-05-22 17:20:28 +00001663 int i;
1664 /* The width of all the shortcuts, except for the last
1665 * two, in the shortcut list in bottomwin. */
1666 int j;
Benno Schulenberg59cd3e62014-05-09 11:44:17 +00001667 /* The calculated index number of the clicked item. */
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001668 size_t currslen;
1669 /* The number of shortcuts in the current shortcut
1670 * list. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001671
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001672 /* Translate the mouse event coordinates so that they're
1673 * relative to bottomwin. */
1674 wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE);
1675
1676 /* Handle releases/clicks of the first mouse button on the
1677 * statusbar elsewhere. */
1678 if (*mouse_y == 0) {
1679 /* Restore the untranslated mouse event coordinates, so
1680 * that they're relative to the entire screen again. */
1681 *mouse_x = mevent.x;
1682 *mouse_y = mevent.y;
1683
1684 return 0;
1685 }
David Lawrence Ramseybc653132007-05-22 17:20:28 +00001686
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001687 /* Get the shortcut lists' length. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001688 if (currmenu == MMAIN)
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001689 currslen = MAIN_VISIBLE;
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001690 else {
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001691 currslen = length_of_list(currmenu);
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001692
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001693 /* We don't show any more shortcuts than the main list
1694 * does. */
1695 if (currslen > MAIN_VISIBLE)
1696 currslen = MAIN_VISIBLE;
1697 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001698
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001699 /* Calculate the width of all of the shortcuts in the list
1700 * except for the last two, which are longer by (COLS % i)
1701 * columns so as to not waste space. */
1702 if (currslen < 2)
1703 i = COLS / (MAIN_VISIBLE / 2);
1704 else
1705 i = COLS / ((currslen / 2) + (currslen % 2));
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001706
Benno Schulenberg59cd3e62014-05-09 11:44:17 +00001707 /* Calculate the one-based index in the shortcut list. */
1708 j = (*mouse_x / i) * 2 + *mouse_y;
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001709
Benno Schulenberg59cd3e62014-05-09 11:44:17 +00001710 /* Adjust the index if we hit the last two wider ones. */
1711 if ((j > currslen) && (*mouse_x % i < COLS % i))
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001712 j -= 2;
Benno Schulenberg0d843012014-04-16 08:24:32 +00001713#ifdef DEBUG
1714 fprintf(stderr, "Calculated %i as index in shortcut list, currmenu = %x.\n", j, currmenu);
1715#endif
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001716 /* Ignore releases/clicks of the first mouse button beyond
1717 * the last shortcut. */
Benno Schulenberg59cd3e62014-05-09 11:44:17 +00001718 if (j > currslen)
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001719 return 2;
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001720
Benno Schulenberg0d843012014-04-16 08:24:32 +00001721 /* Go through the list of functions to determine which
1722 * shortcut in the current menu we released/clicked on. */
Benno Schulenberg59cd3e62014-05-09 11:44:17 +00001723 for (f = allfuncs; f != NULL; f = f->next) {
Benno Schulenberg26de2dd2014-06-27 20:01:27 +00001724 if ((f->menus & currmenu) == 0)
Benno Schulenberg59cd3e62014-05-09 11:44:17 +00001725 continue;
Chris Allegretta1d778232008-08-30 21:00:00 +00001726#ifndef DISABLE_HELP
Benno Schulenberg59cd3e62014-05-09 11:44:17 +00001727 if (!f->help || strlen(f->help) == 0)
1728 continue;
Chris Allegretta1d778232008-08-30 21:00:00 +00001729#endif
Benno Schulenberg59cd3e62014-05-09 11:44:17 +00001730 if (first_sc_for(currmenu, f->scfunc) == NULL)
Benno Schulenberg26de2dd2014-06-27 20:01:27 +00001731 continue;
Benno Schulenberg59cd3e62014-05-09 11:44:17 +00001732 /* Tick off an actually shown shortcut. */
1733 j -= 1;
Benno Schulenberg0d843012014-04-16 08:24:32 +00001734 if (j == 0)
1735 break;
Chris Allegrettac0b78722008-03-11 04:52:57 +00001736 }
Benno Schulenberg0d843012014-04-16 08:24:32 +00001737#ifdef DEBUG
Benno Schulenberg27a52a82014-04-21 13:07:18 +00001738 fprintf(stderr, "Stopped on func %ld present in menus %x\n", (long)f->scfunc, f->menus);
Benno Schulenberg0d843012014-04-16 08:24:32 +00001739#endif
Chris Allegrettac0b78722008-03-11 04:52:57 +00001740
Benno Schulenberg0d843012014-04-16 08:24:32 +00001741 /* And put the corresponding key into the keyboard buffer. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001742 if (f != NULL) {
Benno Schulenberg26de2dd2014-06-27 20:01:27 +00001743 const sc *s = first_sc_for(currmenu, f->scfunc);
Benno Schulenberg62bb6e82014-06-11 19:24:38 +00001744 unget_kbinput(s->seq, s->type == META, s->type == FKEY);
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001745 }
Benno Schulenberga3f421c2014-06-11 18:04:36 +00001746 return 1;
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001747 } else
David Lawrence Ramsey3a504702007-05-29 17:01:12 +00001748 /* Handle releases/clicks of the first mouse button that
1749 * aren't on the current shortcut list elsewhere. */
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001750 return 0;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001751 }
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001752#if NCURSES_MOUSE_VERSION >= 2
1753 /* Handle presses of the fourth mouse button (upward rolls of the
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001754 * mouse wheel) and presses of the fifth mouse button (downward
1755 * rolls of the mouse wheel) . */
1756 else if (mevent.bstate & (BUTTON4_PRESSED | BUTTON5_PRESSED)) {
David Lawrence Ramseydef60912007-12-08 16:59:13 +00001757 bool in_edit = wenclose(edit, *mouse_y, *mouse_x);
David Lawrence Ramseybc653132007-05-22 17:20:28 +00001758
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001759 if (in_bottomwin)
1760 /* Translate the mouse event coordinates so that they're
1761 * relative to bottomwin. */
1762 wmouse_trafo(bottomwin, mouse_y, mouse_x, FALSE);
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001763
David Lawrence Ramsey97a6ecb2007-12-08 04:21:15 +00001764 if (in_edit || (in_bottomwin && *mouse_y == 0)) {
David Lawrence Ramseydef60912007-12-08 16:59:13 +00001765 int i;
1766
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001767 /* One upward roll of the mouse wheel is equivalent to
1768 * moving up three lines, and one downward roll of the mouse
1769 * wheel is equivalent to moving down three lines. */
1770 for (i = 0; i < 3; i++)
1771 unget_kbinput((mevent.bstate & BUTTON4_PRESSED) ?
Benno Schulenberga8a23ab2014-06-10 19:12:14 +00001772 sc_seq_or(do_up_void, 0) : sc_seq_or(do_down_void, 0),
Benno Schulenbergc4520d52014-02-22 19:36:35 +00001773 FALSE, FALSE);
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001774
David Lawrence Ramsey3a5eaeb2007-05-20 23:41:56 +00001775 return 1;
1776 } else
1777 /* Ignore presses of the fourth mouse button and presses of
1778 * the fifth mouse buttons that aren't on the edit window or
1779 * the statusbar. */
1780 return 2;
David Lawrence Ramseyb9fa1b12007-05-15 18:04:25 +00001781 }
1782#endif
David Lawrence Ramseyc8bde572007-06-28 16:38:00 +00001783
1784 /* Ignore all other mouse events. */
1785 return 2;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001786}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001787#endif /* !DISABLE_MOUSE */
1788
Benno Schulenberg7828a802014-04-14 09:22:29 +00001789/* Return the shortcut that corresponds to the values of kbinput (the
1790 * key itself) and meta_key (whether the key is a meta sequence). The
1791 * returned shortcut will be the first in the list that corresponds to
1792 * the given sequence. */
Benno Schulenberg49816fe2014-07-01 10:41:10 +00001793const sc *get_shortcut(int *kbinput)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001794{
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001795 sc *s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001796
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001797#ifdef DEBUG
Benno Schulenberg7e5324d2014-06-30 18:04:33 +00001798 fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %s -- ", *kbinput, meta_key ? "TRUE" : "FALSE");
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001799#endif
1800
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001801 for (s = sclist; s != NULL; s = s->next) {
Benno Schulenberg49816fe2014-07-01 10:41:10 +00001802 if ((currmenu & s->menu) && *kbinput == s->seq
Benno Schulenberg7e5324d2014-06-30 18:04:33 +00001803 && meta_key == (s->type == META)) {
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001804#ifdef DEBUG
Benno Schulenberg7828a802014-04-14 09:22:29 +00001805 fprintf (stderr, "matched seq \"%s\", and btw meta was %d (menu is %x from %x)\n",
Benno Schulenberg49816fe2014-07-01 10:41:10 +00001806 s->keystr, meta_key, currmenu, s->menu);
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001807#endif
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001808 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001809 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001810 }
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001811#ifdef DEBUG
Benno Schulenberg7e5324d2014-06-30 18:04:33 +00001812 fprintf (stderr, "matched nothing, btw meta was %d\n", meta_key);
Chris Allegretta79a33bb2008-03-05 07:34:01 +00001813#endif
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001814
1815 return NULL;
1816}
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
Benno Schulenberg044e4d22014-05-13 21:11:59 +00002009 * 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
Benno Schulenberge7d6e552014-05-10 19:15:04 +00002107 if (interface_color_pair[TITLE_BAR].bright)
2108 wattron(topwin, A_BOLD);
2109 wattron(topwin, interface_color_pair[TITLE_BAR].pairnum);
David Lawrence Ramsey85ffaee2006-07-02 18:29:49 +00002110
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002111 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002112
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002113 /* space has to be at least 4: two spaces before the version message,
2114 * at least one character of the version message, and one space
2115 * after the version message. */
2116 if (space < 4)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002117 space = 0;
2118 else {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002119 /* Limit verlen to 1/3 the length of the screen in columns,
2120 * minus three columns for spaces. */
2121 if (verlen > (COLS / 3) - 3)
2122 verlen = (COLS / 3) - 3;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002123 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002124
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002125 if (space >= 4) {
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002126 /* Add a space after the version message, and account for both
2127 * it and the two spaces before it. */
David Lawrence Ramsey3c43d3d2006-03-30 01:18:29 +00002128 mvwaddnstr(topwin, 0, 2, PACKAGE_STRING,
2129 actual_x(PACKAGE_STRING, verlen));
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002130 verlen += 3;
2131
2132 /* Account for the full length of the version message. */
2133 space -= verlen;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002134 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002135
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002136#ifndef DISABLE_BROWSER
2137 /* Don't display the state if we're in the file browser. */
2138 if (path != NULL)
2139 state = "";
2140 else
2141#endif
2142 state = openfile->modified ? _("Modified") : ISSET(VIEW_MODE) ?
2143 _("View") : "";
2144
David Lawrence Ramsey1904f512007-07-01 21:33:17 +00002145 statelen = strlenpt((*state == '\0' && path == NULL) ?
David Lawrence Ramseye3281692006-07-09 00:50:23 +00002146 _("Modified") : state);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002147
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002148 /* If possible, add a space before state. */
2149 if (space > 0 && statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002150 statelen++;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002151 else
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002152 goto the_end;
2153
2154#ifndef DISABLE_BROWSER
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002155 /* path should be a directory if we're in the file browser. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002156 if (path != NULL)
2157 prefix = _("DIR:");
2158 else
2159#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002160 if (openfile->filename[0] == '\0') {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002161 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002162 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002163 } else
2164 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002165
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002166 prefixlen = strnlenpt(prefix, space - statelen) + 1;
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002167
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002168 /* If newfie is FALSE, add a space after prefix. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002169 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002170 prefixlen++;
2171
David Lawrence Ramsey4ea2eac2006-07-09 00:52:16 +00002172 /* If we're not in the file browser, set path to the current
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002173 * filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002174 if (path == NULL)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002175 path = openfile->filename;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002176
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002177 /* Account for the full lengths of the prefix and the state. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002178 if (space >= prefixlen + statelen)
2179 space -= prefixlen + statelen;
2180 else
2181 space = 0;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002182 /* space is now the room we have for the filename. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002183
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002184 if (!newfie) {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002185 size_t lenpt = strlenpt(path), start_col;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002186
David Lawrence Ramsey8125e082006-11-25 22:27:22 +00002187 /* Don't set dots to TRUE if we have fewer than eight columns
2188 * (i.e. one column for padding, plus seven columns for a
2189 * filename). */
David Lawrence Ramsey49172ca2006-07-13 02:10:27 +00002190 dots = (space >= 8 && lenpt >= space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002191
2192 if (dots) {
2193 start_col = lenpt - space + 3;
2194 space -= 3;
2195 } else
2196 start_col = 0;
2197
2198 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002199 }
2200
David Lawrence Ramsey85ffaee2006-07-02 18:29:49 +00002201 /* If dots is TRUE, we will display something like "File:
2202 * ...ename". */
2203 if (dots) {
2204 mvwaddnstr(topwin, 0, verlen - 1, prefix, actual_x(prefix,
2205 prefixlen));
2206 if (space <= -3 || newfie)
2207 goto the_end;
2208 waddch(topwin, ' ');
2209 waddnstr(topwin, "...", space + 3);
2210 if (space <= 0)
2211 goto the_end;
2212 waddstr(topwin, exppath);
2213 } else {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002214 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2215 /* The length of the expanded filename. */
2216
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002217 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002218 mvwaddnstr(topwin, 0, verlen + ((space - exppathlen) / 3),
2219 prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002220 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002221 waddch(topwin, ' ');
2222 waddstr(topwin, exppath);
2223 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002224 }
2225
2226 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002227 free(exppath);
2228
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002229 if (state[0] != '\0') {
David Lawrence Ramsey3d12f0f2005-10-26 23:14:59 +00002230 if (statelen >= COLS - 1)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002231 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
2232 else {
David Lawrence Ramseycaa86592005-07-10 23:57:32 +00002233 assert(COLS - statelen - 1 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002234
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002235 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002236 actual_x(state, statelen));
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002237 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002238 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002239
Benno Schulenberge7d6e552014-05-10 19:15:04 +00002240 wattroff(topwin, A_BOLD);
2241 wattroff(topwin, interface_color_pair[TITLE_BAR].pairnum);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002242
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002243 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002244 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002245 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002246}
2247
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002248/* Mark the current file as modified if it isn't already, and then
2249 * update the titlebar to display the file's new status. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002250void set_modified(void)
2251{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002252 if (!openfile->modified) {
2253 openfile->modified = TRUE;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002254 titlebar(NULL);
Chris Allegretta21f73f92013-01-03 03:07:27 +00002255#ifndef NANO_TINY
Chris Allegrettad70c7f32013-01-03 03:36:20 +00002256 if (ISSET(LOCKING)) {
Benno Schulenberged0086b2014-06-09 14:33:00 +00002257 if (openfile->filename[0] == '\0')
Chris Allegrettad2f29d02014-01-26 04:09:04 +00002258 return;
2259 else if (openfile->lock_filename == NULL) {
Benno Schulenberg26de2dd2014-06-27 20:01:27 +00002260 /* TRANSLATORS: Try to keep this at most 76 characters. */
2261 statusbar(_("Warning: Modifying a file which is not locked, check directory permission?"));
Chris Allegrettad70c7f32013-01-03 03:36:20 +00002262 } else {
2263 write_lockfile(openfile->lock_filename,
Benno Schulenberg26de2dd2014-06-27 20:01:27 +00002264 get_full_path(openfile->filename), TRUE);
2265 }
Chris Allegrettad70c7f32013-01-03 03:36:20 +00002266 }
Chris Allegretta21f73f92013-01-03 03:07:27 +00002267#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002268 }
2269}
2270
David Lawrence Ramsey5593e202005-06-28 19:49:15 +00002271/* Display a message on the statusbar, and set disable_cursorpos to
2272 * TRUE, so that the message won't be immediately overwritten if
2273 * constant cursor position display is on. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002274void statusbar(const char *msg, ...)
2275{
2276 va_list ap;
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002277 char *bar, *foo;
Benno Schulenberg0c3ced02014-05-04 08:25:09 +00002278 size_t start_x;
Benno Schulenbergeea09082014-04-13 20:50:20 +00002279#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002280 bool old_whitespace;
2281#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002282
2283 va_start(ap, msg);
2284
2285 /* Curses mode is turned off. If we use wmove() now, it will muck
2286 * up the terminal settings. So we just use vfprintf(). */
David Lawrence Ramseyf70f67b2006-06-03 17:31:52 +00002287 if (isendwin()) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002288 vfprintf(stderr, msg, ap);
2289 va_end(ap);
2290 return;
2291 }
2292
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002293 blank_statusbar();
2294
Benno Schulenbergeea09082014-04-13 20:50:20 +00002295#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002296 old_whitespace = ISSET(WHITESPACE_DISPLAY);
2297 UNSET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002298#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002299 bar = charalloc(mb_cur_max() * (COLS - 3));
2300 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
2301 va_end(ap);
2302 foo = display_string(bar, 0, COLS - 4, FALSE);
Benno Schulenberg0c3ced02014-05-04 08:25:09 +00002303 free(bar);
Benno Schulenbergeea09082014-04-13 20:50:20 +00002304#if !defined(NANO_TINY) && !defined(DISABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002305 if (old_whitespace)
2306 SET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002307#endif
Benno Schulenberg0c3ced02014-05-04 08:25:09 +00002308 start_x = (COLS - strlenpt(foo) - 4) / 2;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002309
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002310 wmove(bottomwin, 0, start_x);
Benno Schulenberge7d6e552014-05-10 19:15:04 +00002311 if (interface_color_pair[STATUS_BAR].bright)
2312 wattron(bottomwin, A_BOLD);
2313 wattron(bottomwin, interface_color_pair[STATUS_BAR].pairnum);
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002314 waddstr(bottomwin, "[ ");
2315 waddstr(bottomwin, foo);
2316 free(foo);
2317 waddstr(bottomwin, " ]");
Benno Schulenberge7d6e552014-05-10 19:15:04 +00002318 wattroff(bottomwin, A_BOLD);
2319 wattroff(bottomwin, interface_color_pair[STATUS_BAR].pairnum);
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002320 wnoutrefresh(bottomwin);
2321 reset_cursor();
2322 wnoutrefresh(edit);
2323 /* Leave the cursor at its position in the edit window, not in
2324 * the statusbar. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002325
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002326 disable_cursorpos = TRUE;
David Lawrence Ramseyc6618532005-06-17 22:33:15 +00002327
2328 /* If we're doing quick statusbar blanking, and constant cursor
2329 * position display is off, blank the statusbar after only one
David Lawrence Ramseyce862362006-05-21 21:23:21 +00002330 * keystroke. Otherwise, blank it after twenty-six keystrokes, as
2331 * Pico does. */
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002332 statusblank =
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002333#ifndef NANO_TINY
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002334 ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 :
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002335#endif
David Lawrence Ramseyce862362006-05-21 21:23:21 +00002336 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002337}
2338
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002339/* Display the shortcut list in s on the last two rows of the bottom
2340 * portion of the window. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002341void bottombars(int menu)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002342{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002343 size_t i, colwidth, slen;
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002344 subnfunc *f;
2345 const sc *s;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002346
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002347 if (ISSET(NO_HELP))
2348 return;
2349
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002350 if (menu == MMAIN) {
Chris Allegretta6232d662002-05-12 19:52:15 +00002351 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002352
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002353 assert(slen <= length_of_list(menu));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002354 } else {
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002355 slen = length_of_list(menu);
Chris Allegretta6232d662002-05-12 19:52:15 +00002356
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002357 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002358 if (slen > MAIN_VISIBLE)
2359 slen = MAIN_VISIBLE;
2360 }
2361
David Lawrence Ramseye806ab82006-04-18 16:13:35 +00002362 /* There will be this many characters per column, except for the
2363 * last two, which will be longer by (COLS % colwidth) columns so as
2364 * to not waste space. We need at least three columns to display
2365 * anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002366 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002367
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002368 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002369
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002370#ifdef DEBUG
2371 fprintf(stderr, "In bottombars, and slen == \"%d\"\n", (int) slen);
2372#endif
Chris Allegretta658399a2001-06-14 02:54:22 +00002373
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002374 for (f = allfuncs, i = 0; i < slen && f != NULL; f = f->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +00002375
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002376#ifdef DEBUG
Benno Schulenberg26de2dd2014-06-27 20:01:27 +00002377 fprintf(stderr, "Checking menu items....");
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002378#endif
Benno Schulenberg26de2dd2014-06-27 20:01:27 +00002379 if ((f->menus & menu) == 0)
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002380 continue;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002381
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002382#ifdef DEBUG
Benno Schulenberg26de2dd2014-06-27 20:01:27 +00002383 fprintf(stderr, "found one! f->menus = %x, desc = \"%s\"\n", f->menus, f->desc);
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002384#endif
Benno Schulenberg26de2dd2014-06-27 20:01:27 +00002385 s = first_sc_for(menu, f->scfunc);
2386 if (s == NULL) {
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002387#ifdef DEBUG
2388 fprintf(stderr, "Whoops, guess not, no shortcut key found for func!\n");
2389#endif
Benno Schulenberg26de2dd2014-06-27 20:01:27 +00002390 continue;
2391 }
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002392 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002393#ifdef DEBUG
Benno Schulenberg26de2dd2014-06-27 20:01:27 +00002394 fprintf(stderr, "Calling onekey with keystr \"%s\" and desc \"%s\"\n", s->keystr, f->desc);
Chris Allegretta79a33bb2008-03-05 07:34:01 +00002395#endif
Chris Allegretta1fb25fd2008-03-18 03:06:27 +00002396 onekey(s->keystr, _(f->desc), colwidth + (COLS % colwidth));
Benno Schulenberg26de2dd2014-06-27 20:01:27 +00002397 i++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002398 }
2399
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002400 wnoutrefresh(bottomwin);
2401 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002402 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002403}
2404
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002405/* Write a shortcut key to the help area at the bottom of the window.
2406 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2407 * to write at most len characters, even if len is very small and
2408 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2409 * the whole string! We do not bother padding the entry with blanks. */
2410void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002411{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002412 size_t keystroke_len = strlenpt(keystroke) + 1;
2413
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002414 assert(keystroke != NULL && desc != NULL);
2415
Benno Schulenberge7d6e552014-05-10 19:15:04 +00002416 if (interface_color_pair[KEY_COMBO].bright)
2417 wattron(bottomwin, A_BOLD);
2418 wattron(bottomwin, interface_color_pair[KEY_COMBO].pairnum);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002419 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
Benno Schulenberge7d6e552014-05-10 19:15:04 +00002420 wattroff(bottomwin, A_BOLD);
2421 wattroff(bottomwin, interface_color_pair[KEY_COMBO].pairnum);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002422
2423 if (len > keystroke_len)
2424 len -= keystroke_len;
2425 else
2426 len = 0;
2427
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002428 if (len > 0) {
2429 waddch(bottomwin, ' ');
Benno Schulenberge7d6e552014-05-10 19:15:04 +00002430 if (interface_color_pair[FUNCTION_TAG].bright)
2431 wattron(bottomwin, A_BOLD);
2432 wattron(bottomwin, interface_color_pair[FUNCTION_TAG].pairnum);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002433 waddnstr(bottomwin, desc, actual_x(desc, len));
Benno Schulenberge7d6e552014-05-10 19:15:04 +00002434 wattroff(bottomwin, A_BOLD);
2435 wattroff(bottomwin, interface_color_pair[FUNCTION_TAG].pairnum);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002436 }
2437}
2438
David Lawrence Ramsey2b9d6a02005-11-01 17:45:31 +00002439/* Reset current_y, based on the position of current, and put the cursor
2440 * in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002441void reset_cursor(void)
2442{
Chris Allegretta05417a22009-08-17 07:52:10 +00002443 size_t xpt;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002444 /* If we haven't opened any files yet, put the cursor in the top
2445 * left corner of the edit window and get out. */
David Lawrence Ramseydbcaa3b2005-07-08 20:59:24 +00002446 if (openfile == NULL) {
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002447 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002448 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002449 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002450
Chris Allegretta05417a22009-08-17 07:52:10 +00002451 xpt = xplustabs();
David Lawrence Ramsey964722a2006-05-26 03:02:50 +00002452
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002453#ifndef NANO_TINY
Chris Allegretta05417a22009-08-17 07:52:10 +00002454 if (ISSET(SOFTWRAP)) {
Chris Allegretta05417a22009-08-17 07:52:10 +00002455 filestruct *tmp;
Chris Allegretta6f083322009-11-11 06:00:33 +00002456 openfile->current_y = 0;
Chris Allegretta05417a22009-08-17 07:52:10 +00002457
Chris Allegretta6f083322009-11-11 06:00:33 +00002458 for (tmp = openfile->edittop; tmp && tmp != openfile->current; tmp = tmp->next)
Benno Schulenberg6af5bde2014-06-09 20:41:15 +00002459 openfile->current_y += (strlenpt(tmp->data) / COLS) + 1;
Chris Allegretta6f083322009-11-11 06:00:33 +00002460
2461 openfile->current_y += xplustabs() / COLS;
Chris Allegretta05417a22009-08-17 07:52:10 +00002462 if (openfile->current_y < editwinrows)
Chris Allegretta6f083322009-11-11 06:00:33 +00002463 wmove(edit, openfile->current_y, xpt % COLS);
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002464 } else
2465#endif
2466 {
Chris Allegretta05417a22009-08-17 07:52:10 +00002467 openfile->current_y = openfile->current->lineno -
2468 openfile->edittop->lineno;
2469
2470 if (openfile->current_y < editwinrows)
2471 wmove(edit, openfile->current_y, xpt - get_page_start(xpt));
2472 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002473}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002474
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002475/* edit_draw() takes care of the job of actually painting a line into
2476 * the edit window. fileptr is the line to be painted, at row line of
2477 * the window. converted is the actual string to be written to the
2478 * window, with tabs and control characters replaced by strings of
2479 * regular characters. start is the column number of the first
2480 * character of this page. That is, the first character of converted
2481 * corresponds to character number actual_x(fileptr->data, start) of the
2482 * line. */
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002483void edit_draw(filestruct *fileptr, const char *converted, int
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002484 line, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002485{
Benno Schulenberg00389922014-04-04 11:59:03 +00002486#if !defined(NANO_TINY) || !defined(DISABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002487 size_t startpos = actual_x(fileptr->data, start);
2488 /* The position in fileptr->data of the leftmost character
2489 * that displays at least partially on the window. */
2490 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2491 /* The position in fileptr->data of the first character that is
2492 * completely off the window to the right.
2493 *
2494 * Note that endpos might be beyond the null terminator of the
2495 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002496#endif
2497
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002498 assert(openfile != NULL && fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002499 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002500
Benno Schulenbergeb5c49d2014-05-19 20:44:24 +00002501 /* First simply paint the line -- then we'll add colors or the
2502 * marking highlight on just the pieces that need it. */
2503 mvwaddstr(edit, line, 0, converted);
Benno Schulenberg1de337d2014-06-04 16:02:51 +00002504
Chris Allegrettacfa29762014-05-28 01:35:51 +00002505#ifndef USE_SLANG
Benno Schulenberg1de337d2014-06-04 16:02:51 +00002506 /* Tell ncurses to really redraw the line without trying to optimize
2507 * for what it thinks is already there, because it gets it wrong in
2508 * the case of a wide character in column zero. See bug #31743. */
Benno Schulenberg0ae38b42014-05-23 20:24:31 +00002509 wredrawln(edit, line, 1);
Chris Allegrettacfa29762014-05-28 01:35:51 +00002510#endif
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002511
Benno Schulenberg00389922014-04-04 11:59:03 +00002512#ifndef DISABLE_COLOR
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002513 /* If color syntaxes are available and turned on, we need to display
2514 * them. */
2515 if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
2516 const colortype *tmpcolor = openfile->colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002517
Benno Schulenberg1de337d2014-06-04 16:02:51 +00002518 /* Set up multi-line color data for this line if it's not yet
2519 * calculated. */
2520 if (fileptr->multidata == NULL && openfile->syntax
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002521 && openfile->syntax->nmultis > 0) {
Benno Schulenberga65ef422014-03-17 21:36:37 +00002522 int i;
Benno Schulenberg1de337d2014-06-04 16:02:51 +00002523 fileptr->multidata = (short *)nmalloc(openfile->syntax->nmultis * sizeof(short));
2524 for (i = 0; i < openfile->syntax->nmultis; i++)
2525 /* Assume this applies until we know otherwise. */
2526 fileptr->multidata[i] = -1;
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002527 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002528 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2529 int x_start;
2530 /* Starting column for mvwaddnstr. Zero-based. */
2531 int paintlen;
David Lawrence Ramsey2ea7fb02006-08-02 18:41:55 +00002532 /* Number of chars to paint on this line. There are
2533 * COLS characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002534 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002535 /* Index in converted where we paint. */
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002536 regmatch_t startmatch;
2537 /* Match position for start_regex. */
2538 regmatch_t endmatch;
2539 /* Match position for end_regex. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002540
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002541 if (tmpcolor->bright)
2542 wattron(edit, A_BOLD);
2543 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramseyb0e04c02005-12-08 07:24:54 +00002544 /* Two notes about regexec(). A return value of zero means
2545 * that there is a match. Also, rm_eo is the first
2546 * non-matching character after the match. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002547
Chris Allegretta22c83ec2013-03-17 22:09:38 +00002548 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002549 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002550 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002551
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002552 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002553 * last match. Even though two matches may overlap, we
David Lawrence Ramsey2ef7dae2006-05-26 11:58:37 +00002554 * want to ignore them, so that we can highlight e.g. C
2555 * strings correctly. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002556 while (k < endpos) {
2557 /* Note the fifth parameter to regexec(). It says
2558 * not to match the beginning-of-line character
David Lawrence Ramsey2ef7dae2006-05-26 11:58:37 +00002559 * unless k is zero. If regexec() returns
2560 * REG_NOMATCH, there are no more matches in the
2561 * line. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002562 if (regexec(tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002563 &startmatch, (k == 0) ? 0 : REG_NOTBOL) ==
2564 REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002565 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002566 /* Translate the match to the beginning of the
2567 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002568 startmatch.rm_so += k;
2569 startmatch.rm_eo += k;
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002570
2571 /* Skip over a zero-length regex match. */
2572 if (startmatch.rm_so == startmatch.rm_eo)
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002573 startmatch.rm_eo++;
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002574 else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002575 startmatch.rm_eo > startpos) {
David Lawrence Ramseyb02a1952006-05-08 16:25:12 +00002576 x_start = (startmatch.rm_so <= startpos) ? 0 :
2577 strnlenpt(fileptr->data,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002578 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002579
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002580 index = actual_x(converted, x_start);
2581
2582 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00002583 strnlenpt(fileptr->data,
2584 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002585
2586 assert(0 <= x_start && 0 <= paintlen);
2587
Chris Allegretta22c83ec2013-03-17 22:09:38 +00002588 mvwaddnstr(edit, line, x_start, converted +
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002589 index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002590 }
Chris Allegretta22c83ec2013-03-17 22:09:38 +00002591 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002592 }
Chris Allegretta56a295b2009-02-07 14:48:30 +00002593 } else if (fileptr->multidata != NULL && fileptr->multidata[tmpcolor->id] != CNONE) {
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002594 /* This is a multi-line regex. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002595 * First, we have to see if the beginning of the line is
2596 * colored by a start on an earlier line, and an end on
2597 * this line or later.
2598 *
2599 * We find the first line before fileptr matching the
2600 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002601 * end, then go to step two. Otherwise, find the next
2602 * line after start_line matching the end. If that line
2603 * is not before fileptr, then paint the beginning of
2604 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002605 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002606 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002607 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002608 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002609 const filestruct *end_line;
Chris Allegretta364763f2009-02-03 05:05:58 +00002610 short md = fileptr->multidata[tmpcolor->id];
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002611
Chris Allegretta364763f2009-02-03 05:05:58 +00002612 if (md == -1)
Benno Schulenberg1de337d2014-06-04 16:02:51 +00002613 /* Assume this until we know otherwise. */
2614 fileptr->multidata[tmpcolor->id] = CNONE;
Chris Allegretta364763f2009-02-03 05:05:58 +00002615 else if (md == CNONE)
Benno Schulenberg3be5f462014-05-17 20:25:42 +00002616 goto end_of_loop;
Chris Allegretta364763f2009-02-03 05:05:58 +00002617 else if (md == CWHOLELINE) {
2618 mvwaddnstr(edit, line, 0, converted, -1);
Benno Schulenberg3be5f462014-05-17 20:25:42 +00002619 goto end_of_loop;
Chris Allegretta803379c2009-02-07 07:09:31 +00002620 } else if (md == CBEGINBEFORE) {
2621 regexec(tmpcolor->end, fileptr->data, 1, &endmatch, 0);
2622 paintlen = actual_x(converted, strnlenpt(fileptr->data,
2623 endmatch.rm_eo) - start);
2624 mvwaddnstr(edit, line, 0, converted, paintlen);
Benno Schulenberg3be5f462014-05-17 20:25:42 +00002625 goto end_of_loop;
Chris Allegretta364763f2009-02-03 05:05:58 +00002626 }
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002627
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002628 while (start_line != NULL && regexec(tmpcolor->start,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002629 start_line->data, 1, &startmatch, 0) ==
2630 REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002631 /* If there is an end on this line, there is no need
2632 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002633 if (regexec(tmpcolor->end, start_line->data, 0,
2634 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002635 goto step_two;
2636 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002637 }
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002638
2639 /* Skip over a zero-length regex match. */
2640 if (startmatch.rm_so == startmatch.rm_eo)
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002641 startmatch.rm_eo++;
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002642 else {
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002643 /* No start found, so skip to the next step. */
2644 if (start_line == NULL)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002645 goto step_two;
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002646 /* Now start_line is the first line before fileptr
2647 * containing a start match. Is there a start on
2648 * this line not followed by an end on this line? */
2649 start_col = 0;
2650 while (TRUE) {
2651 start_col += startmatch.rm_so;
2652 startmatch.rm_eo -= startmatch.rm_so;
2653 if (regexec(tmpcolor->end, start_line->data +
2654 start_col + startmatch.rm_eo, 0, NULL,
2655 (start_col + startmatch.rm_eo == 0) ?
2656 0 : REG_NOTBOL) == REG_NOMATCH)
2657 /* No end found after this start. */
2658 break;
2659 start_col++;
2660 if (regexec(tmpcolor->start, start_line->data +
2661 start_col, 1, &startmatch,
2662 REG_NOTBOL) == REG_NOMATCH)
2663 /* No later start on this line. */
2664 goto step_two;
2665 }
2666 /* Indeed, there is a start not followed on this
2667 * line by an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002668
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002669 /* We have already checked that there is no end
2670 * before fileptr and after the start. Is there an
2671 * end after the start at all? We don't paint
2672 * unterminated starts. */
2673 end_line = fileptr;
2674 while (end_line != NULL && regexec(tmpcolor->end,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002675 end_line->data, 1, &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002676 end_line = end_line->next;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002677
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002678 /* No end found, or it is too early. */
2679 if (end_line == NULL || (end_line == fileptr &&
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002680 endmatch.rm_eo <= startpos))
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002681 goto step_two;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002682
David Lawrence Ramseycbab2732006-08-02 18:38:45 +00002683 /* Now paint the start of fileptr. If the start of
2684 * fileptr is on a different line from the end,
2685 * paintlen is -1, meaning that everything on the
2686 * line gets painted. Otherwise, paintlen is the
2687 * expanded location of the end of the match minus
2688 * the expanded location of the beginning of the
2689 * page. */
Chris Allegretta364763f2009-02-03 05:05:58 +00002690 if (end_line != fileptr) {
David Lawrence Ramsey1c9dd102006-11-21 17:05:04 +00002691 paintlen = -1;
Chris Allegretta364763f2009-02-03 05:05:58 +00002692 fileptr->multidata[tmpcolor->id] = CWHOLELINE;
2693 } else {
David Lawrence Ramsey1c9dd102006-11-21 17:05:04 +00002694 paintlen = actual_x(converted,
2695 strnlenpt(fileptr->data,
2696 endmatch.rm_eo) - start);
Chris Allegretta364763f2009-02-03 05:05:58 +00002697 fileptr->multidata[tmpcolor->id] = CBEGINBEFORE;
2698 }
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002699 mvwaddnstr(edit, line, 0, converted, paintlen);
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002700 step_two:
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002701 /* Second step, we look for starts on this line. */
2702 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002703
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002704 while (start_col < endpos) {
2705 if (regexec(tmpcolor->start, fileptr->data +
2706 start_col, 1, &startmatch, (start_col ==
2707 0) ? 0 : REG_NOTBOL) == REG_NOMATCH ||
2708 start_col + startmatch.rm_so >= endpos)
2709 /* No more starts on this line. */
2710 break;
2711 /* Translate the match to be relative to the
2712 * beginning of the line. */
2713 startmatch.rm_so += start_col;
2714 startmatch.rm_eo += start_col;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002715
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002716 x_start = (startmatch.rm_so <= startpos) ? 0 :
2717 strnlenpt(fileptr->data,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002718 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002719
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002720 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002721
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002722 if (regexec(tmpcolor->end, fileptr->data +
2723 startmatch.rm_eo, 1, &endmatch,
2724 (startmatch.rm_eo == 0) ? 0 :
2725 REG_NOTBOL) == 0) {
2726 /* Translate the end match to be relative to
2727 * the beginning of the line. */
2728 endmatch.rm_so += startmatch.rm_eo;
2729 endmatch.rm_eo += startmatch.rm_eo;
2730 /* There is an end on this line. But does
2731 * it appear on this page, and is the match
2732 * more than zero characters long? */
2733 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002734 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002735 paintlen = actual_x(converted + index,
2736 strnlenpt(fileptr->data,
2737 endmatch.rm_eo) - start -
2738 x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002739
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002740 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002741
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002742 mvwaddnstr(edit, line, x_start,
2743 converted + index, paintlen);
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002744 if (paintlen > 0)
Chris Allegretta364763f2009-02-03 05:05:58 +00002745 fileptr->multidata[tmpcolor->id] = CSTARTENDHERE;
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00002746
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002747 }
2748 } else {
2749 /* There is no end on this line. But we
2750 * haven't yet looked for one on later
2751 * lines. */
2752 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002753
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002754 while (end_line != NULL &&
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002755 regexec(tmpcolor->end, end_line->data,
2756 0, NULL, 0) == REG_NOMATCH)
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002757 end_line = end_line->next;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002758
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002759 if (end_line != NULL) {
2760 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002761
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002762 mvwaddnstr(edit, line, x_start,
2763 converted + index, -1);
2764 /* We painted to the end of the line, so
2765 * don't bother checking any more
2766 * starts. */
Chris Allegretta364763f2009-02-03 05:05:58 +00002767 fileptr->multidata[tmpcolor->id] = CENDAFTER;
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002768 break;
2769 }
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002770 }
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002771 start_col = startmatch.rm_so + 1;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002772 }
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002773 }
2774 }
Benno Schulenberg3be5f462014-05-17 20:25:42 +00002775 end_of_loop:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002776 wattroff(edit, A_BOLD);
2777 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002778 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002779 }
Benno Schulenberg00389922014-04-04 11:59:03 +00002780#endif /* !DISABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002781
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002782#ifndef NANO_TINY
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002783 /* If the mark is on, we need to display it. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002784 if (openfile->mark_set && (fileptr->lineno <=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002785 openfile->mark_begin->lineno || fileptr->lineno <=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002786 openfile->current->lineno) && (fileptr->lineno >=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002787 openfile->mark_begin->lineno || fileptr->lineno >=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002788 openfile->current->lineno)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002789 /* fileptr is at least partially selected. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002790 const filestruct *top;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002791 /* Either current or mark_begin, whichever is first. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002792 size_t top_x;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002793 /* current_x or mark_begin_x, corresponding to top. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002794 const filestruct *bot;
2795 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002796 int x_start;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002797 /* Starting column for mvwaddnstr(). Zero-based. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002798 int paintlen;
David Lawrence Ramseyc6bef762006-08-02 19:13:31 +00002799 /* Number of characters to paint on this line. There are
2800 * COLS characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002801 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002802 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002803
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00002804 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002805
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002806 if (top->lineno < fileptr->lineno || top_x < startpos)
2807 top_x = startpos;
2808 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2809 bot_x = endpos;
2810
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002811 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002812 if (top_x < endpos && bot_x > startpos) {
2813 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002814
2815 /* x_start is the expanded location of the beginning of the
2816 * mark minus the beginning of the page. */
2817 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002818
David Lawrence Ramseycbab2732006-08-02 18:38:45 +00002819 /* If the end of the mark is off the page, paintlen is -1,
2820 * meaning that everything on the line gets painted.
2821 * Otherwise, paintlen is the expanded location of the end
2822 * of the mark minus the expanded location of the beginning
2823 * of the mark. */
David Lawrence Ramsey1c9dd102006-11-21 17:05:04 +00002824 if (bot_x >= endpos)
2825 paintlen = -1;
2826 else
2827 paintlen = strnlenpt(fileptr->data, bot_x) - (x_start +
2828 start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002829
2830 /* If x_start is before the beginning of the page, shift
2831 * paintlen x_start characters to compensate, and put
2832 * x_start at the beginning of the page. */
2833 if (x_start < 0) {
2834 paintlen += x_start;
2835 x_start = 0;
2836 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002837
2838 assert(x_start >= 0 && x_start <= strlen(converted));
2839
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002840 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002841
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002842 if (paintlen > 0)
2843 paintlen = actual_x(converted + index, paintlen);
2844
Benno Schulenbergc9700352014-05-04 08:53:06 +00002845 wattron(edit, hilite_attribute);
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002846 mvwaddnstr(edit, line, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00002847 paintlen);
Benno Schulenbergc9700352014-05-04 08:53:06 +00002848 wattroff(edit, hilite_attribute);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002849 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002850 }
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002851#endif /* !NANO_TINY */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002852}
2853
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002854/* Just update one line in the edit buffer. This is basically a wrapper
David Lawrence Ramseyb3c6b402005-11-07 06:20:02 +00002855 * for edit_draw(). The line will be displayed starting with
Chris Allegretta05417a22009-08-17 07:52:10 +00002856 * fileptr->data[index]. Likely arguments are current_x or zero.
Benno Schulenbergd0dec312014-04-08 12:35:18 +00002857 * Returns: Number of additional lines consumed (needed for SOFTWRAP). */
Chris Allegretta05417a22009-08-17 07:52:10 +00002858int update_line(filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002859{
Chris Allegretta05417a22009-08-17 07:52:10 +00002860 int line = 0;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002861 /* The line in the edit window that we want to update. */
Benno Schulenbergf876ee12014-04-15 11:25:29 +00002862 int extralinesused = 0;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002863 char *converted;
2864 /* fileptr->data converted to have tabs and control characters
2865 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002866 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002867
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002868 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002869
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002870#ifndef NANO_TINY
Chris Allegretta05417a22009-08-17 07:52:10 +00002871 if (ISSET(SOFTWRAP)) {
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002872 filestruct *tmp;
2873
Benno Schulenberg6af5bde2014-06-09 20:41:15 +00002874 for (tmp = openfile->edittop; tmp && tmp != fileptr; tmp = tmp->next)
2875 line += (strlenpt(tmp->data) / COLS) + 1;
Chris Allegretta05417a22009-08-17 07:52:10 +00002876 } else
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002877#endif
Chris Allegretta05417a22009-08-17 07:52:10 +00002878 line = fileptr->lineno - openfile->edittop->lineno;
2879
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002880 if (line < 0 || line >= editwinrows)
Chris Allegrettad233e7e2009-09-15 04:51:09 +00002881 return 1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002882
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002883 /* First, blank out the line. */
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002884 blank_line(edit, line, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002885
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002886 /* Next, convert variables that index the line to their equivalent
2887 * positions in the expanded line. */
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002888#ifndef NANO_TINY
Chris Allegretta05417a22009-08-17 07:52:10 +00002889 if (ISSET(SOFTWRAP))
2890 index = 0;
2891 else
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002892#endif
Chris Allegretta05417a22009-08-17 07:52:10 +00002893 index = strnlenpt(fileptr->data, index);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002894 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002895
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002896 /* Expand the line, replacing tabs with spaces, and control
2897 * characters with their displayed forms. */
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002898#ifdef NANO_TINY
2899 converted = display_string(fileptr->data, page_start, COLS, TRUE);
2900#else
Chris Allegretta6f083322009-11-11 06:00:33 +00002901 converted = display_string(fileptr->data, page_start, COLS, !ISSET(SOFTWRAP));
Chris Allegretta6f083322009-11-11 06:00:33 +00002902#ifdef DEBUG
2903 if (ISSET(SOFTWRAP) && strlen(converted) >= COLS - 2)
Benno Schulenberg505125e2014-06-09 14:23:53 +00002904 fprintf(stderr, "update_line(): converted(1) line = %s\n", converted);
Chris Allegretta6f083322009-11-11 06:00:33 +00002905#endif
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002906#endif /* !NANO_TINY */
Chris Allegretta6f083322009-11-11 06:00:33 +00002907
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002908 /* Paint the line. */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002909 edit_draw(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002910 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002911
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002912#ifndef NANO_TINY
Chris Allegretta05417a22009-08-17 07:52:10 +00002913 if (!ISSET(SOFTWRAP)) {
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002914#endif
Chris Allegretta05417a22009-08-17 07:52:10 +00002915 if (page_start > 0)
2916 mvwaddch(edit, line, 0, '$');
2917 if (strlenpt(fileptr->data) > page_start + COLS)
2918 mvwaddch(edit, line, COLS - 1, '$');
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002919#ifndef NANO_TINY
Chris Allegretta05417a22009-08-17 07:52:10 +00002920 } else {
Benno Schulenberg53435b02014-06-10 19:07:47 +00002921 size_t full_length = strlenpt(fileptr->data);
Chris Allegretta6f083322009-11-11 06:00:33 +00002922 for (index += COLS; index <= full_length && line < editwinrows; index += COLS) {
Chris Allegretta05417a22009-08-17 07:52:10 +00002923 line++;
2924#ifdef DEBUG
Benno Schulenberg53435b02014-06-10 19:07:47 +00002925 fprintf(stderr, "update_line(): softwrap code, moving to %d index %lu\n", line, (unsigned long)index);
Chris Allegretta05417a22009-08-17 07:52:10 +00002926#endif
Benno Schulenberg71c9a522014-05-13 20:14:01 +00002927 blank_line(edit, line, 0, COLS);
Chris Allegretta05417a22009-08-17 07:52:10 +00002928
2929 /* Expand the line, replacing tabs with spaces, and control
Benno Schulenberg71c9a522014-05-13 20:14:01 +00002930 * characters with their displayed forms. */
Chris Allegretta6f083322009-11-11 06:00:33 +00002931 converted = display_string(fileptr->data, index, COLS, !ISSET(SOFTWRAP));
2932#ifdef DEBUG
2933 if (ISSET(SOFTWRAP) && strlen(converted) >= COLS - 2)
2934 fprintf(stderr, "update_line(): converted(2) line = %s\n", converted);
2935#endif
Chris Allegretta05417a22009-08-17 07:52:10 +00002936
2937 /* Paint the line. */
2938 edit_draw(fileptr, converted, line, index);
Benno Schulenberg71c9a522014-05-13 20:14:01 +00002939 free(converted);
Chris Allegretta05417a22009-08-17 07:52:10 +00002940 extralinesused++;
2941 }
2942 }
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00002943#endif /* !NANO_TINY */
Chris Allegretta05417a22009-08-17 07:52:10 +00002944 return extralinesused;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002945}
2946
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002947/* Return TRUE if we need an update after moving horizontally, and FALSE
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002948 * otherwise. We need one if the mark is on or if pww_save and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002949 * placewewant are on different pages. */
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002950bool need_horizontal_update(size_t pww_save)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002951{
2952 return
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002953#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002954 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002955#endif
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002956 get_page_start(pww_save) !=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002957 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002958}
2959
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002960/* Return TRUE if we need an update after moving vertically, and FALSE
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002961 * otherwise. We need one if the mark is on or if pww_save and
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002962 * placewewant are on different pages. */
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002963bool need_vertical_update(size_t pww_save)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002964{
2965 return
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002966#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002967 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002968#endif
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00002969 get_page_start(pww_save) !=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002970 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002971}
2972
Chris Allegretta99c8d402009-11-13 13:48:56 +00002973/* When edittop changes, try and figure out how many lines
Benno Schulenbergd0dec312014-04-08 12:35:18 +00002974 * we really have to work with (i.e. set maxrows). */
Chris Allegretta99c8d402009-11-13 13:48:56 +00002975void compute_maxrows(void)
2976{
2977 int n;
2978 filestruct *foo = openfile->edittop;
2979
Chris Allegretta8c1edd12009-11-16 04:28:40 +00002980 if (!ISSET(SOFTWRAP)) {
2981 maxrows = editwinrows;
2982 return;
2983 }
2984
Chris Allegretta99c8d402009-11-13 13:48:56 +00002985 maxrows = 0;
2986 for (n = 0; n < editwinrows && foo; n++) {
Benno Schulenbergd0dec312014-04-08 12:35:18 +00002987 maxrows++;
Chris Allegrettae2df2c82009-11-24 17:15:53 +00002988 n += strlenpt(foo->data) / COLS;
Chris Allegretta99c8d402009-11-13 13:48:56 +00002989 foo = foo->next;
2990 }
2991
Chris Allegretta8c1edd12009-11-16 04:28:40 +00002992 if (n < editwinrows)
2993 maxrows += editwinrows - n;
2994
Chris Allegretta99c8d402009-11-13 13:48:56 +00002995#ifdef DEBUG
Benno Schulenbergacda2552014-06-09 15:08:59 +00002996 fprintf(stderr, "compute_maxrows(): maxrows = %d\n", maxrows);
Chris Allegretta99c8d402009-11-13 13:48:56 +00002997#endif
Chris Allegretta99c8d402009-11-13 13:48:56 +00002998}
2999
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003000/* Scroll the edit window in the given direction and the given number
3001 * of lines, and draw new lines on the blank lines left after the
Benno Schulenbergce0ea442014-06-23 18:20:12 +00003002 * scrolling. direction is the direction to scroll, either UPWARD or
3003 * DOWNWARD, and nlines is the number of lines to scroll. We change
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00003004 * edittop, and assume that current and current_x are up to date. We
3005 * also assume that scrollok(edit) is FALSE. */
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003006void edit_scroll(scroll_dir direction, ssize_t nlines)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003007{
Benno Schulenberga8353bd2014-03-17 13:15:50 +00003008 ssize_t i;
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00003009 filestruct *foo;
Chris Allegretta139934a2009-08-30 03:50:16 +00003010 bool do_redraw = FALSE;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003011
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003012 /* Don't bother scrolling less than one line. */
3013 if (nlines < 1)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003014 return;
3015
Chris Allegretta5687c3d2009-09-03 02:48:35 +00003016 if (need_vertical_update(0))
Chris Allegretta139934a2009-08-30 03:50:16 +00003017 do_redraw = TRUE;
3018
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003019 /* Part 1: nlines is the number of lines we're going to scroll the
3020 * text of the edit window. */
3021
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003022 /* Move the top line of the edit window up or down (depending on the
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003023 * value of direction) nlines lines, or as many lines as we can if
3024 * there are fewer than nlines lines available. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003025 for (i = nlines; i > 0; i--) {
Benno Schulenbergce0ea442014-06-23 18:20:12 +00003026 if (direction == UPWARD) {
David Lawrence Ramseye99223d2005-11-10 04:27:30 +00003027 if (openfile->edittop == openfile->fileage)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003028 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003029 openfile->edittop = openfile->edittop->prev;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003030 } else {
David Lawrence Ramseye99223d2005-11-10 04:27:30 +00003031 if (openfile->edittop == openfile->filebot)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003032 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003033 openfile->edittop = openfile->edittop->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003034 }
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00003035
3036#ifndef NANO_TINY
Benno Schulenbergf876ee12014-04-15 11:25:29 +00003037 /* Don't over-scroll on long lines. */
Benno Schulenbergce0ea442014-06-23 18:20:12 +00003038 if (ISSET(SOFTWRAP) && direction == UPWARD) {
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003039 ssize_t len = strlenpt(openfile->edittop->data) / COLS;
Benno Schulenberg52e35332014-05-16 11:03:04 +00003040 i -= len;
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003041 if (len > 0)
3042 do_redraw = TRUE;
3043 }
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00003044#endif
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003045 }
3046
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00003047 /* Limit nlines to the number of lines we could scroll. */
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00003048 nlines -= i;
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00003049
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00003050 /* Don't bother scrolling zero lines or more than the number of
3051 * lines in the edit window minus one; in both cases, get out, and
David Lawrence Ramsey1072fce2007-09-16 16:53:20 +00003052 * call edit_refresh() beforehand if we need to. */
Chris Allegretta139934a2009-08-30 03:50:16 +00003053 if (nlines == 0 || do_redraw || nlines >= editwinrows) {
David Lawrence Ramsey1072fce2007-09-16 16:53:20 +00003054 if (do_redraw || nlines >= editwinrows)
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003055 edit_refresh_needed = TRUE;
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00003056 return;
3057 }
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003058
3059 /* Scroll the text of the edit window up or down nlines lines,
3060 * depending on the value of direction. */
David Lawrence Ramsey47bb8882005-07-22 22:56:03 +00003061 scrollok(edit, TRUE);
Benno Schulenbergce0ea442014-06-23 18:20:12 +00003062 wscrl(edit, (direction == UPWARD) ? -nlines : nlines);
David Lawrence Ramsey47bb8882005-07-22 22:56:03 +00003063 scrollok(edit, FALSE);
3064
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003065 /* Part 2: nlines is the number of lines in the scrolled region of
3066 * the edit window that we need to draw. */
3067
David Lawrence Ramsey68346502005-08-16 03:03:15 +00003068 /* If the top or bottom line of the file is now visible in the edit
3069 * window, we need to draw the entire edit window. */
Benno Schulenbergce0ea442014-06-23 18:20:12 +00003070 if ((direction == UPWARD && openfile->edittop ==
3071 openfile->fileage) || (direction == DOWNWARD &&
David Lawrence Ramsey6ff22e72006-07-19 00:14:52 +00003072 openfile->edittop->lineno + editwinrows - 1 >=
3073 openfile->filebot->lineno))
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00003074 nlines = editwinrows;
David Lawrence Ramseya7f488b2005-07-17 02:19:47 +00003075
David Lawrence Ramseya6eb8482006-01-10 07:51:49 +00003076 /* If the scrolled region contains only one line, and the line
3077 * before it is visible in the edit window, we need to draw it too.
3078 * If the scrolled region contains more than one line, and the lines
3079 * before and after the scrolled region are visible in the edit
3080 * window, we need to draw them too. */
3081 nlines += (nlines == 1) ? 1 : 2;
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00003082
David Lawrence Ramseyde0c5eb2005-07-17 22:51:44 +00003083 if (nlines > editwinrows)
3084 nlines = editwinrows;
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003085
3086 /* If we scrolled up, we're on the line before the scrolled
3087 * region. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003088 foo = openfile->edittop;
David Lawrence Ramsey14588912005-07-14 20:37:01 +00003089
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003090 /* If we scrolled down, move down to the line before the scrolled
3091 * region. */
Benno Schulenbergce0ea442014-06-23 18:20:12 +00003092 if (direction == DOWNWARD) {
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003093 for (i = editwinrows - nlines; i > 0 && foo != NULL; i--)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003094 foo = foo->next;
3095 }
3096
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003097 /* Draw new lines on any blank lines before or inside the scrolled
3098 * region. If we scrolled down and we're on the top line, or if we
3099 * scrolled up and we're on the bottom line, the line won't be
3100 * blank, so we don't need to draw it unless the mark is on or we're
3101 * not on the first page. */
3102 for (i = nlines; i > 0 && foo != NULL; i--) {
Benno Schulenbergce0ea442014-06-23 18:20:12 +00003103 if ((i == nlines && direction == DOWNWARD) || (i == 1 &&
3104 direction == UPWARD)) {
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003105 if (do_redraw)
3106 update_line(foo, (foo == openfile->current) ?
3107 openfile->current_x : 0);
3108 } else
3109 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003110 openfile->current_x : 0);
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003111 foo = foo->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003112 }
Benno Schulenbergdf7bba32014-02-26 11:38:30 +00003113 compute_maxrows();
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003114}
3115
3116/* Update any lines between old_current and current that need to be
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00003117 * updated. Use this if we've moved without changing any text. */
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00003118void edit_redraw(filestruct *old_current, size_t pww_save)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003119{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003120 bool do_redraw = need_vertical_update(0) ||
David Lawrence Ramseyfa387952006-08-26 16:50:51 +00003121 need_vertical_update(pww_save);
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00003122 filestruct *foo = NULL;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003123
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003124 /* If either old_current or current is offscreen, scroll the edit
3125 * window until it's onscreen and get out. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003126 if (old_current->lineno < openfile->edittop->lineno ||
3127 old_current->lineno >= openfile->edittop->lineno +
Chris Allegretta99c8d402009-11-13 13:48:56 +00003128 maxrows || openfile->current->lineno <
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003129 openfile->edittop->lineno || openfile->current->lineno >=
Chris Allegretta99c8d402009-11-13 13:48:56 +00003130 openfile->edittop->lineno + maxrows) {
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003131#ifdef DEBUG
Benno Schulenbergacda2552014-06-09 15:08:59 +00003132 fprintf(stderr, "edit_redraw(): line %ld was offscreen, oldcurrent = %ld edittop = %ld",
3133 (long)openfile->current->lineno, (long)old_current->lineno, (long)openfile->edittop->lineno);
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003134#endif
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003135
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003136#ifndef NANO_TINY
3137 /* If the mark is on, update all the lines between old_current
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003138 * and either the old first line or old last line (depending on
3139 * whether we've scrolled up or down) of the edit window. */
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003140 if (openfile->mark_set) {
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003141 ssize_t old_lineno;
Chris Allegretta4cc24622013-01-03 04:23:10 +00003142 filestruct *old_edittop = openfile->edittop;
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003143
3144 if (old_edittop->lineno < openfile->edittop->lineno)
3145 old_lineno = old_edittop->lineno;
3146 else
Chris Allegretta99c8d402009-11-13 13:48:56 +00003147 old_lineno = (old_edittop->lineno + maxrows <=
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003148 openfile->filebot->lineno) ?
3149 old_edittop->lineno + editwinrows :
3150 openfile->filebot->lineno;
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003151
3152 foo = old_current;
3153
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003154 while (foo->lineno != old_lineno) {
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003155 update_line(foo, 0);
3156
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003157 foo = (foo->lineno > old_lineno) ? foo->prev :
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003158 foo->next;
3159 }
3160 }
3161#endif /* !NANO_TINY */
3162
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003163 /* Put edittop in range of current, get the difference in lines
3164 * between the original edittop and the current edittop, and
3165 * then restore the original edittop. */
Chris Allegretta374216f2010-01-04 19:00:55 +00003166 edit_update(CENTER);
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00003167
David Lawrence Ramseyb0063672006-07-06 18:29:37 +00003168 /* Update old_current if we're not on the same page as
3169 * before. */
David Lawrence Ramseya6eb8482006-01-10 07:51:49 +00003170 if (do_redraw)
3171 update_line(old_current, 0);
3172
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003173#ifndef NANO_TINY
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003174 /* If the mark is on, update all the lines between the old first
3175 * line or old last line of the edit window (depending on
3176 * whether we've scrolled up or down) and current. */
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003177 if (openfile->mark_set) {
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003178 while (foo->lineno != openfile->current->lineno) {
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003179 update_line(foo, 0);
3180
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00003181 foo = (foo->lineno > openfile->current->lineno) ?
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00003182 foo->prev : foo->next;
3183 }
3184 }
3185#endif /* !NANO_TINY */
3186
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003187 return;
3188 }
3189
David Lawrence Ramseyb0063672006-07-06 18:29:37 +00003190 /* Update old_current and current if we're not on the same page as
3191 * before. If the mark is on, update all the lines between
3192 * old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003193 foo = old_current;
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003194
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003195 while (foo != openfile->current) {
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003196 if (do_redraw)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003197 update_line(foo, 0);
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003198
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00003199#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003200 if (!openfile->mark_set)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003201#endif
3202 break;
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003203
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00003204#ifndef NANO_TINY
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003205 foo = (foo->lineno > openfile->current->lineno) ? foo->prev :
3206 foo->next;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003207#endif
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003208 }
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003209
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003210 if (do_redraw)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003211 update_line(openfile->current, openfile->current_x);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003212}
3213
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00003214/* Refresh the screen without changing the position of lines. Use this
3215 * if we've moved and changed text. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003216void edit_refresh(void)
3217{
Chris Allegrettad47d8cd2009-01-25 07:25:17 +00003218 filestruct *foo;
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003219 int nlines;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003220
Benno Schulenbergf876ee12014-04-15 11:25:29 +00003221 /* Figure out what maxrows should really be. */
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003222 compute_maxrows();
Chris Allegretta99c8d402009-11-13 13:48:56 +00003223
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003224 if (openfile->current->lineno < openfile->edittop->lineno ||
3225 openfile->current->lineno >= openfile->edittop->lineno +
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003226 maxrows) {
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003227#ifdef DEBUG
Benno Schulenbergacda2552014-06-09 15:08:59 +00003228 fprintf(stderr, "edit_refresh(): line = %ld, edittop %ld + maxrows %d\n",
3229 (long)openfile->current->lineno, (long)openfile->edittop->lineno, maxrows);
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003230#endif
3231
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003232 /* Put the top line of the edit window in range of the current
3233 * line. */
Chris Allegretta374216f2010-01-04 19:00:55 +00003234 edit_update(CENTER);
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003235 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003236
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003237 foo = openfile->edittop;
3238
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003239#ifdef DEBUG
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003240 fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", (long)openfile->edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003241#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003242
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003243 for (nlines = 0; nlines < editwinrows && foo != NULL; nlines++) {
Chris Allegretta05417a22009-08-17 07:52:10 +00003244 nlines += update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003245 openfile->current_x : 0);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003246 foo = foo->next;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003247 }
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003248
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003249 for (; nlines < editwinrows; nlines++)
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003250 blank_line(edit, nlines, 0, COLS);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003251
3252 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00003253 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003254}
3255
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003256/* Move edittop to put it in range of current, keeping current in the
3257 * same place. location determines how we move it: if it's CENTER, we
3258 * center current, and if it's NONE, we put current current_y lines
3259 * below edittop. */
David Lawrence Ramseybf0e47d2005-08-01 18:27:10 +00003260void edit_update(update_type location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003261{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003262 filestruct *foo = openfile->current;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003263 int goal;
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003264
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003265 /* If location is CENTER, we move edittop up (editwinrows / 2)
3266 * lines. This puts current at the center of the screen. If
3267 * location is NONE, we move edittop up current_y lines if current_y
3268 * is in range of the screen, 0 lines if current_y is less than 0,
3269 * or (editwinrows - 1) lines if current_y is greater than
3270 * (editwinrows - 1). This puts current at the same place on the
3271 * screen as before, or at the top or bottom of the screen if
3272 * edittop is beyond either. */
3273 if (location == CENTER)
Chris Allegretta374216f2010-01-04 19:00:55 +00003274 goal = editwinrows / 2;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003275 else {
3276 goal = openfile->current_y;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003277
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003278 /* Limit goal to (editwinrows - 1) lines maximum. */
Chris Allegretta374216f2010-01-04 19:00:55 +00003279 if (goal > editwinrows - 1)
3280 goal = editwinrows - 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003281 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003282
Chris Allegretta35afab52009-09-13 04:50:44 +00003283 for (; goal > 0 && foo->prev != NULL; goal--) {
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003284 foo = foo->prev;
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00003285#ifndef NANO_TINY
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003286 if (ISSET(SOFTWRAP) && foo)
3287 goal -= strlenpt(foo->data) / COLS;
Benno Schulenberg1102aaa2014-06-09 20:26:54 +00003288#endif
Chris Allegretta35afab52009-09-13 04:50:44 +00003289 }
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003290 openfile->edittop = foo;
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003291#ifdef DEBUG
Benno Schulenberg53435b02014-06-10 19:07:47 +00003292 fprintf(stderr, "edit_update(): setting edittop to lineno %ld\n", (long)openfile->edittop->lineno);
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003293#endif
Chris Allegretta8c1edd12009-11-16 04:28:40 +00003294 compute_maxrows();
Chris Allegretta1a7a91b2010-01-13 03:21:19 +00003295 edit_refresh_needed = TRUE;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003296}
3297
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003298/* Unconditionally redraw the entire screen. */
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003299void total_redraw(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003300{
David Lawrence Ramseyf78bc852007-12-18 15:55:48 +00003301#ifdef USE_SLANG
3302 /* Slang curses emulation brain damage, part 4: Slang doesn't define
3303 * curscr. */
3304 SLsmg_touch_screen();
3305 SLsmg_refresh();
3306#else
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00003307 wrefresh(curscr);
David Lawrence Ramseyf78bc852007-12-18 15:55:48 +00003308#endif
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003309}
3310
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003311/* Unconditionally redraw the entire screen, and then refresh it using
3312 * the current file. */
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003313void total_refresh(void)
3314{
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003315 total_redraw();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003316 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003317 edit_refresh();
Chris Allegretta79a33bb2008-03-05 07:34:01 +00003318 bottombars(currmenu);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003319}
3320
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003321/* Display the main shortcut list on the last two rows of the bottom
3322 * portion of the window. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003323void display_main_list(void)
3324{
Benno Schulenberg00389922014-04-04 11:59:03 +00003325#ifndef DISABLE_COLOR
Chris Allegretta5575bfa2014-02-24 10:18:15 +00003326 if (openfile->syntax && openfile->syntax->linter)
3327 set_lint_shortcuts();
3328 else
3329 set_spell_shortcuts();
3330#endif
3331
Chris Allegretta79a33bb2008-03-05 07:34:01 +00003332 bottombars(MMAIN);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003333}
3334
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003335/* If constant is TRUE, we display the current cursor position only if
3336 * disable_cursorpos is FALSE. Otherwise, we display it
3337 * unconditionally and set disable_cursorpos to FALSE. If constant is
3338 * TRUE and disable_cursorpos is TRUE, we also set disable_cursorpos to
3339 * FALSE, so that we leave the current statusbar alone this time, and
3340 * display the current cursor position next time. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003341void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003342{
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003343 filestruct *f;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003344 char c;
David Lawrence Ramsey5745c0a2005-07-31 20:20:37 +00003345 size_t i, cur_xpt = xplustabs() + 1;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003346 size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003347 int linepct, colpct, charpct;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003348
David Lawrence Ramsey4ab80152005-07-31 18:51:51 +00003349 assert(openfile->fileage != NULL && openfile->current != NULL);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003350
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003351 f = openfile->current->next;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003352 c = openfile->current->data[openfile->current_x];
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003353
3354 openfile->current->next = NULL;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003355 openfile->current->data[openfile->current_x] = '\0';
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003356
3357 i = get_totsize(openfile->fileage, openfile->current);
3358
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003359 openfile->current->data[openfile->current_x] = c;
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003360 openfile->current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003361
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003362 if (constant && disable_cursorpos) {
3363 disable_cursorpos = FALSE;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003364 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003365 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003366
David Lawrence Ramseyb94d51a2007-04-19 03:15:04 +00003367 /* Display the current cursor position on the statusbar, and set
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003368 * disable_cursorpos to FALSE. */
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003369 linepct = 100 * openfile->current->lineno /
3370 openfile->filebot->lineno;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003371 colpct = 100 * cur_xpt / cur_lenpt;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003372 charpct = (openfile->totsize == 0) ? 0 : 100 * i /
3373 openfile->totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003374
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003375 statusbar(
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003376 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003377 (long)openfile->current->lineno,
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003378 (long)openfile->filebot->lineno, linepct,
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003379 (unsigned long)cur_xpt, (unsigned long)cur_lenpt, colpct,
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003380 (unsigned long)i, (unsigned long)openfile->totsize, charpct);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003381
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003382 disable_cursorpos = FALSE;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003383}
3384
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003385/* Unconditionally display the current cursor position. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003386void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003387{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003388 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003389}
3390
Chris Allegretta0dc26dc2009-01-24 22:40:41 +00003391void enable_nodelay(void)
3392{
Benno Schulenberg492e9f62014-06-20 10:48:26 +00003393 nodelay_mode = TRUE;
3394 nodelay(edit, TRUE);
Chris Allegretta0dc26dc2009-01-24 22:40:41 +00003395}
3396
3397void disable_nodelay(void)
3398{
Benno Schulenberg492e9f62014-06-20 10:48:26 +00003399 nodelay_mode = FALSE;
3400 nodelay(edit, FALSE);
Chris Allegretta0dc26dc2009-01-24 22:40:41 +00003401}
3402
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003403/* Highlight the current word being replaced or spell checked. We
3404 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003405void do_replace_highlight(bool highlight, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003406{
David Lawrence Ramsey6168cb72005-06-30 03:53:28 +00003407 size_t y = xplustabs(), word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003408
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003409 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003410 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003411 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003412
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003413 assert(y > 0);
3414
3415 if (word_len > y)
3416 y--;
3417
Chris Allegrettafb62f732000-12-05 11:36:41 +00003418 reset_cursor();
David Lawrence Ramsey98958e82007-12-04 16:38:47 +00003419 wnoutrefresh(edit);
Chris Allegretta598106e2002-01-19 01:59:37 +00003420
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003421 if (highlight)
Benno Schulenbergc9700352014-05-04 08:53:06 +00003422 wattron(edit, hilite_attribute);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003423
David Lawrence Ramsey21b946e2006-11-10 20:13:38 +00003424 /* This is so we can show zero-length matches. */
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003425 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00003426 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003427 else
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003428 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003429
3430 if (word_len > y)
3431 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003432
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003433 if (highlight)
Benno Schulenbergc9700352014-05-04 08:53:06 +00003434 wattroff(edit, hilite_attribute);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003435}
3436
Benno Schulenbergd17438b2014-04-03 20:57:44 +00003437#ifndef DISABLE_EXTRA
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003438#define CREDIT_LEN 57
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003439#define XLCREDIT_LEN 8
3440
David Lawrence Ramsey8ad58bc2005-08-16 03:02:46 +00003441/* Easter egg: Display credits. Assume nodelay(edit) and scrollok(edit)
3442 * are FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003443void do_credits(void)
3444{
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003445 bool old_more_space = ISSET(MORE_SPACE);
3446 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003447 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003448 const char *credits[CREDIT_LEN] = {
3449 NULL, /* "The nano text editor" */
3450 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003451 VERSION,
3452 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003453 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003454 "Chris Allegretta",
3455 "Jordi Mallach",
3456 "Adam Rogoyski",
3457 "Rob Siemborski",
3458 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003459 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003460 "David Benbennick",
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003461 "Mike Frysinger",
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003462 "Benno Schulenberg",
Chris Allegretta598106e2002-01-19 01:59:37 +00003463 "Ken Tyler",
3464 "Sven Guckes",
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003465 NULL, /* credits[16], handled below. */
Chris Allegretta598106e2002-01-19 01:59:37 +00003466 "Pauli Virtanen",
3467 "Daniele Medri",
3468 "Clement Laforet",
3469 "Tedi Heriyanto",
3470 "Bill Soudan",
3471 "Christian Weisgerber",
3472 "Erik Andersen",
3473 "Big Gaute",
3474 "Joshua Jensen",
3475 "Ryan Krebs",
3476 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003477 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003478 NULL, /* "Special thanks to:" */
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003479 "Monique, Brielle & Joseph",
Chris Allegretta598106e2002-01-19 01:59:37 +00003480 "Plattsburgh State University",
3481 "Benet Laboratories",
3482 "Amy Allegretta",
3483 "Linda Young",
3484 "Jeremy Robichaud",
3485 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003486 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003487 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003488 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003489 "Thomas Dickey",
3490 "Pavel Curtis",
3491 "Zeyd Ben-Halim",
3492 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003493 NULL, /* "and anyone else we forgot..." */
3494 NULL, /* "Thank you for using nano!" */
3495 "",
3496 "",
3497 "",
3498 "",
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003499 "(C) 1999 - 2014",
David Lawrence Ramseyd8a1d372007-10-11 05:01:32 +00003500 "Free Software Foundation, Inc.",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003501 "",
3502 "",
3503 "",
3504 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003505 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003506 };
3507
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003508 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003509 N_("The nano text editor"),
3510 N_("version"),
3511 N_("Brought to you by:"),
3512 N_("Special thanks to:"),
3513 N_("The Free Software Foundation"),
3514 N_("For ncurses:"),
3515 N_("and anyone else we forgot..."),
3516 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003517 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003518
Benno Schulenbergd0dec312014-04-08 12:35:18 +00003519 /* credits[16]: Make sure this name is displayed properly, since we
David Lawrence Ramsey62d616b2005-07-06 19:20:32 +00003520 * can't dynamically assign it above, using Unicode 00F6 (Latin
3521 * Small Letter O with Diaresis) if applicable. */
Chris Allegretta34b7f1c2014-02-24 15:15:51 +00003522 credits[16] =
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00003523#ifdef ENABLE_UTF8
Benno Schulenberga8a23ab2014-06-10 19:12:14 +00003524 using_utf8() ? "Florian K\xC3\xB6nig" :
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003525#endif
3526 "Florian K\xF6nig";
3527
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003528 if (!old_more_space || !old_no_help) {
3529 SET(MORE_SPACE);
3530 SET(NO_HELP);
3531 window_init();
3532 }
3533
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003534 curs_set(0);
3535 nodelay(edit, TRUE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003536
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003537 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003538 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003539 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003540 blank_statusbar();
3541 blank_bottombars();
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003542
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003543 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003544 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003545 wrefresh(bottomwin);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003546 napms(700);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003547
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003548 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003549 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003550 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003551
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003552 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003553 const char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003554 size_t start_x;
3555
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003556 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003557 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003558
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003559 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003560 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003561 } else
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003562 what = credits[crpos];
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003563
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003564 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003565 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
3566 start_x, what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003567 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003568
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003569 wrefresh(edit);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003570
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003571 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003572 break;
3573 napms(700);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003574
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003575 scrollok(edit, TRUE);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003576 wscrl(edit, 1);
3577 scrollok(edit, FALSE);
3578 wrefresh(edit);
3579
3580 if ((kbinput = wgetch(edit)) != ERR)
3581 break;
3582 napms(700);
3583
3584 scrollok(edit, TRUE);
3585 wscrl(edit, 1);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003586 scrollok(edit, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003587 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003588 }
3589
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003590 if (kbinput != ERR)
3591 ungetch(kbinput);
3592
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003593 if (!old_more_space || !old_no_help) {
3594 UNSET(MORE_SPACE);
3595 UNSET(NO_HELP);
3596 window_init();
3597 }
3598
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003599 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003600 nodelay(edit, FALSE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003601
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003602 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003603}
Benno Schulenbergd17438b2014-04-03 20:57:44 +00003604#endif /* !DISABLE_EXTRA */