blob: 9acdb85401b5333abf28d5544efa4015d814d41a [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * winio.c *
4 * *
David Lawrence Ramsey315eb322005-11-28 19:35:29 +00005 * Copyright (C) 1999-2004 Chris Allegretta *
David Lawrence Ramsey47cfd192006-01-02 04:30:33 +00006 * Copyright (C) 2005-2006 David Lawrence Ramsey *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00007 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00009 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000010 * any later version. *
11 * *
David Lawrence Ramsey6e925cf2005-05-15 19:57:17 +000012 * This program is distributed in the hope that it will be useful, but *
13 * WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
15 * General Public License for more details. *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000016 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
David Lawrence Ramsey6e925cf2005-05-15 19:57:17 +000019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
20 * 02110-1301, USA. *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000021 * *
22 **************************************************************************/
23
David Lawrence Ramsey034b9942005-12-08 02:47:10 +000024#include "proto.h"
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000025
David Lawrence Ramsey143b8c72005-11-01 18:35:47 +000026#include <stdio.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000027#include <stdarg.h>
28#include <string.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000029#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000030#include <ctype.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000031
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +000032static int *key_buffer = NULL;
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +000033 /* The keystroke buffer, containing all the keystrokes we have
34 * 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 Ramsey95b98502006-04-25 13:07:31 +000073 * console, the FreeBSD console, the Mach console, xterm, rxvt, and
74 * Eterm. Among these, there are several conflicts and omissions,
75 * 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
101 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000102 *
103 * Note that Center (5) on the numeric keypad with NumLock off can also
104 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000105
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000106/* Read in a sequence of keystrokes from win and save them in the
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000107 * keystroke buffer. This should only be called when the keystroke
108 * buffer is empty. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000109void get_key_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000110{
David Lawrence Ramseyec8a0552006-03-19 19:26:52 +0000111 int input;
112 size_t errcount;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000113
114 /* If the keystroke buffer isn't empty, get out. */
115 if (key_buffer != NULL)
116 return;
117
118 /* Read in the first character using blocking input. */
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000119#ifndef NANO_TINY
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000120 allow_pending_sigwinch(TRUE);
121#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000122
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +0000123 /* Just before reading in the first character, display any pending
124 * screen updates. */
125 doupdate();
126
David Lawrence Ramsey91493252006-03-19 19:25:29 +0000127 errcount = 0;
David Lawrence Ramsey6f5de422005-10-06 05:28:37 +0000128 while ((input = wgetch(win)) == ERR) {
David Lawrence Ramsey91493252006-03-19 19:25:29 +0000129 errcount++;
130
David Lawrence Ramsey354597f2006-03-24 16:04:44 +0000131 /* If we've failed to get a character MAX_BUF_SIZE times in a
132 * row, assume that the input source we were using is gone and
David Lawrence Ramsey9b33d512006-03-20 04:46:48 +0000133 * die gracefully. We could check if errno is set to EIO
134 * ("Input/output error") and die gracefully in that case, but
135 * it's not always set properly. Argh. */
David Lawrence Ramsey354597f2006-03-24 16:04:44 +0000136 if (errcount == MAX_BUF_SIZE)
David Lawrence Ramsey6f5de422005-10-06 05:28:37 +0000137 handle_hupterm(0);
138 }
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000139
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000140#ifndef NANO_TINY
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000141 allow_pending_sigwinch(FALSE);
142#endif
143
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000144 /* Increment the length of the keystroke buffer, save the value of
145 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000146 * is an extended keypad value or FALSE if it isn't. */
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
165 /* Otherwise, increment the length of the keystroke buffer, save
166 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000167 * if the keystroke is an extended keypad value or FALSE if it
168 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000169 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000170 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
171 sizeof(int));
172 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000173
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000174#ifndef NANO_TINY
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000175 allow_pending_sigwinch(FALSE);
176#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000177 }
178
179 /* Switch back to non-blocking input. */
180 nodelay(win, FALSE);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000181
182#ifdef DEBUG
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000183 fprintf(stderr, "get_key_buffer(): key_buffer_len = %lu\n", (unsigned long)key_buffer_len);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000184#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000185}
186
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000187/* Return the length of the keystroke buffer. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000188size_t get_key_buffer_len(void)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000189{
190 return key_buffer_len;
191}
192
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000193/* Add the keystrokes in input to the keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000194void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000195{
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000196#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000197 allow_pending_sigwinch(TRUE);
198 allow_pending_sigwinch(FALSE);
199#endif
200
201 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000202 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000203 return;
204
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000205 /* If adding input would put the keystroke buffer beyond maximum
206 * capacity, only add enough of input to put it at maximum
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000207 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000208 if (key_buffer_len + input_len < key_buffer_len)
209 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000210
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000211 /* Add the length of input to the length of the keystroke buffer,
212 * and reallocate the keystroke buffer so that it has enough room
213 * for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000214 key_buffer_len += input_len;
215 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
216 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000217
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000218 /* If the keystroke buffer wasn't empty before, move its beginning
219 * forward far enough so that we can add input to its beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000220 if (key_buffer_len > input_len)
221 memmove(key_buffer + input_len, key_buffer,
222 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000223
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000224 /* Copy input to the beginning of the keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000225 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000226}
227
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000228/* Put back the character stored in kbinput, putting it in byte range
229 * beforehand. If meta_key is TRUE, put back the Escape character after
230 * putting back kbinput. If func_key is TRUE, put back the function key
231 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000232void unget_kbinput(int kbinput, bool meta_key, bool func_key)
233{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000234 if (!func_key)
235 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000236
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000237 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000238
239 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000240 kbinput = NANO_CONTROL_3;
241 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000242 }
243}
244
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000245/* Try to read input_len characters from the keystroke buffer. If the
246 * keystroke buffer is empty and win isn't NULL, try to read in more
247 * characters from win and add them to the keystroke buffer before doing
248 * anything else. If the keystroke buffer is empty and win is NULL,
249 * return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000250int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000251{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000252 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000253
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000254#ifndef NANO_TINY
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000255 allow_pending_sigwinch(TRUE);
256 allow_pending_sigwinch(FALSE);
257#endif
258
259 if (key_buffer_len == 0) {
260 if (win != NULL)
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000261 get_key_buffer(win);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000262
263 if (key_buffer_len == 0)
264 return NULL;
265 }
266
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000267 /* If input_len is greater than the length of the keystroke buffer,
268 * only read the number of characters in the keystroke buffer. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000269 if (input_len > key_buffer_len)
270 input_len = key_buffer_len;
271
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000272 /* Subtract input_len from the length of the keystroke buffer, and
273 * allocate input so that it has enough room for input_len
274 * keystrokes. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000275 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000276 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000277
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000278 /* Copy input_len keystrokes from the beginning of the keystroke
279 * buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000280 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000281
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000282 /* If the keystroke buffer is empty, mark it as such. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000283 if (key_buffer_len == 0) {
284 free(key_buffer);
285 key_buffer = NULL;
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +0000286 /* If the keystroke buffer isn't empty, move its beginning forward
287 * far enough so that the keystrokes in input are no longer at its
288 * beginning. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000289 } else {
290 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000291 sizeof(int));
292 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
293 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000294 }
295
296 return input;
297}
298
299/* Read in a single character. If it's ignored, swallow it and go on.
300 * Otherwise, try to translate it from ASCII, meta key sequences, escape
301 * sequences, and/or extended keypad values. Set meta_key to TRUE when
302 * we get a meta key sequence, and set func_key to TRUE when we get an
303 * extended keypad value. Supported extended keypad values consist of
304 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
305 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
306 * the function keypad (F1-F16), and the numeric keypad with NumLock
307 * off. Assume nodelay(win) is FALSE. */
308int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
309{
310 int kbinput;
311
312 /* Read in a character and interpret it. Continue doing this until
313 * we get a recognized value or sequence. */
David Lawrence Ramseyfc0f8f82006-05-10 13:41:53 +0000314 while ((kbinput = parse_kbinput(win, meta_key, func_key)) == ERR);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000315
David Lawrence Ramsey6b49e9e2006-05-22 01:29:30 +0000316 /* If we read from the edit window, blank the statusbar if we need
317 * to. */
318 if (win == edit)
David Lawrence Ramseyce862362006-05-21 21:23:21 +0000319 check_statusblank();
320
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000321 return kbinput;
322}
323
324/* Translate ASCII characters, extended keypad values, and escape
325 * sequences into their corresponding key values. Set meta_key to TRUE
326 * when we get a meta key sequence, and set func_key to TRUE when we get
327 * a function key. Assume nodelay(win) is FALSE. */
David Lawrence Ramseyfc0f8f82006-05-10 13:41:53 +0000328int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000329{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000330 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000331 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000332
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000333 *meta_key = FALSE;
334 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000335
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000336 /* Read in a character. */
337 while ((kbinput = get_input(win, 1)) == NULL);
338
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000339 switch (*kbinput) {
340 case ERR:
341 break;
342 case NANO_CONTROL_3:
343 /* Increment the escape counter. */
344 escapes++;
345 switch (escapes) {
346 case 1:
347 /* One escape: wait for more input. */
348 case 2:
349 /* Two escapes: wait for more input. */
350 break;
351 default:
352 /* More than two escapes: reset the escape counter
353 * and wait for more input. */
354 escapes = 0;
355 }
356 break;
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000357#if !defined(NANO_TINY) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000358 /* Since we don't change the default SIGWINCH handler when
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000359 * NANO_TINY is defined, KEY_RESIZE is never generated. Also,
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000360 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
361 case KEY_RESIZE:
362 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000363#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000364#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000365 case KEY_SHIFT_L:
366 case KEY_SHIFT_R:
367 case KEY_CONTROL_L:
368 case KEY_CONTROL_R:
369 case KEY_ALT_L:
370 case KEY_ALT_R:
371 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000372#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000373 default:
374 switch (escapes) {
375 case 0:
376 switch (*kbinput) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000377 case KEY_DOWN:
378 retval = NANO_NEXTLINE_KEY;
379 break;
380 case KEY_UP:
381 retval = NANO_PREVLINE_KEY;
382 break;
383 case KEY_LEFT:
384 retval = NANO_BACK_KEY;
385 break;
386 case KEY_RIGHT:
387 retval = NANO_FORWARD_KEY;
388 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000389#ifdef KEY_HOME
David Lawrence Ramseyf70eca02006-05-13 14:59:17 +0000390 /* HP-UX 10-11 doesn't support KEY_HOME. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000391 case KEY_HOME:
392 retval = NANO_HOME_KEY;
393 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000394#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000395 case KEY_BACKSPACE:
396 retval = NANO_BACKSPACE_KEY;
397 break;
398 case KEY_DC:
399 retval = ISSET(REBIND_DELETE) ?
400 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
401 break;
402 case KEY_IC:
403 retval = NANO_INSERTFILE_KEY;
404 break;
405 case KEY_NPAGE:
406 retval = NANO_NEXTPAGE_KEY;
407 break;
408 case KEY_PPAGE:
409 retval = NANO_PREVPAGE_KEY;
410 break;
411 case KEY_ENTER:
412 retval = NANO_ENTER_KEY;
413 break;
414 case KEY_A1: /* Home (7) on numeric keypad
415 * with NumLock off. */
416 retval = NANO_HOME_KEY;
417 break;
418 case KEY_A3: /* PageUp (9) on numeric keypad
419 * with NumLock off. */
420 retval = NANO_PREVPAGE_KEY;
421 break;
422 case KEY_B2: /* Center (5) on numeric keypad
423 * with NumLock off. */
424 break;
425 case KEY_C1: /* End (1) on numeric keypad
426 * with NumLock off. */
427 retval = NANO_END_KEY;
428 break;
429 case KEY_C3: /* PageDown (4) on numeric
430 * keypad with NumLock off. */
431 retval = NANO_NEXTPAGE_KEY;
432 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000433#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000434 /* Slang doesn't support KEY_BEG. */
435 case KEY_BEG: /* Center (5) on numeric keypad
436 * with NumLock off. */
437 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000438#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000439#ifdef KEY_END
David Lawrence Ramseyf70eca02006-05-13 14:59:17 +0000440 /* HP-UX 10-11 doesn't support KEY_END. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000441 case KEY_END:
442 retval = NANO_END_KEY;
443 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000444#endif
David Lawrence Ramsey475c4022006-01-30 01:32:41 +0000445#ifdef KEY_SBEG
446 /* Slang doesn't support KEY_SBEG. */
447 case KEY_SBEG: /* Center (5) on numeric keypad
448 * with NumLock off. */
449 break;
450#endif
451#ifdef KEY_SDC
452 /* Slang doesn't support KEY_SDC. */
453 case KEY_SDC:
David Lawrence Ramsey3a5e6f92006-01-30 21:23:51 +0000454 retval = ISSET(REBIND_DELETE) ?
455 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
David Lawrence Ramsey475c4022006-01-30 01:32:41 +0000456 break;
457#endif
458#ifdef KEY_SEND
David Lawrence Ramseya01f1312006-05-13 15:03:09 +0000459 /* HP-UX 10-11 and Slang don't support
460 * KEY_SEND. */
David Lawrence Ramsey475c4022006-01-30 01:32:41 +0000461 case KEY_SEND:
462 retval = NANO_END_KEY;
463 break;
464#endif
465#ifdef KEY_SHOME
David Lawrence Ramseyf70eca02006-05-13 14:59:17 +0000466 /* HP-UX 10-11 and Slang don't support
David Lawrence Ramsey475c4022006-01-30 01:32:41 +0000467 * KEY_SHOME. */
468 case KEY_SHOME:
469 retval = NANO_HOME_KEY;
470 break;
471#endif
472#ifdef KEY_SIC
473 /* Slang doesn't support KEY_SIC. */
474 case KEY_SIC:
475 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000476 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000477#endif
478#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000479 /* Slang doesn't support KEY_SLEFT. */
480 case KEY_SLEFT:
481 retval = NANO_BACK_KEY;
482 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000483#endif
484#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000485 /* Slang doesn't support KEY_SRIGHT. */
486 case KEY_SRIGHT:
487 retval = NANO_FORWARD_KEY;
488 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000489#endif
David Lawrence Ramsey475c4022006-01-30 01:32:41 +0000490#ifdef KEY_SSUSPEND
491 /* Slang doesn't support KEY_SSUSPEND. */
492 case KEY_SSUSPEND:
493 retval = NANO_SUSPEND_KEY;
494 break;
495#endif
496#ifdef KEY_SUSPEND
497 /* Slang doesn't support KEY_SUSPEND. */
498 case KEY_SUSPEND:
499 retval = NANO_SUSPEND_KEY;
500 break;
501#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000502 default:
503 retval = *kbinput;
504 break;
505 }
506 break;
507 case 1:
508 /* One escape followed by a non-escape: escape
509 * sequence mode. Reset the escape counter. If
510 * there aren't any other keys waiting, we have a
511 * meta key sequence, so set meta_key to TRUE and
512 * save the lowercase version of the non-escape
513 * character as the result. If there are other keys
514 * waiting, we have a true escape sequence, so
515 * interpret it. */
516 escapes = 0;
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000517 if (get_key_buffer_len() == 0) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000518 *meta_key = TRUE;
519 retval = tolower(*kbinput);
David Lawrence Ramseyf1022082006-06-08 02:01:49 +0000520 } else {
521 bool ignore_seq;
522
523 retval = parse_escape_seq_kbinput(*kbinput,
524 &ignore_seq);
525
526 /* If the escape sequence is unrecognized and
527 * not ignored, throw it out. */
David Lawrence Ramsey2d0d60b2006-06-08 02:05:34 +0000528 if (retval == ERR && !ignore_seq) {
David Lawrence Ramseyf1022082006-06-08 02:01:49 +0000529 if (win == edit)
530 statusbar(_("Unknown Command"));
531 beep();
532 }
533 }
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000534 break;
535 case 2:
536 /* Two escapes followed by one or more decimal
David Lawrence Ramsey38f70a52005-07-19 18:46:02 +0000537 * digits: byte sequence mode. If the byte
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000538 * sequence's range is limited to 2XX (the first
539 * digit is in the '0' to '2' range and it's the
540 * first digit, or it's in the '0' to '9' range and
541 * it's not the first digit), increment the byte
542 * sequence counter and interpret the digit. If the
543 * byte sequence's range is not limited to 2XX, fall
544 * through. */
David Lawrence Ramseye2afdbb2006-05-27 14:46:56 +0000545 if (('0' <= *kbinput && *kbinput <= '2' &&
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000546 byte_digits == 0) || ('0' <= *kbinput &&
547 *kbinput <= '9' && byte_digits > 0)) {
548 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000549
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000550 byte_digits++;
David Lawrence Ramseyfc0f8f82006-05-10 13:41:53 +0000551 byte = get_byte_kbinput(*kbinput);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000552
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000553 if (byte != ERR) {
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000554 char *byte_mb;
555 int byte_mb_len, *seq, i;
556
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000557 /* If we've read in a complete byte
558 * sequence, reset the byte sequence counter
559 * and the escape counter, and put back the
560 * corresponding byte value. */
561 byte_digits = 0;
562 escapes = 0;
563
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000564 /* Put back the multibyte equivalent of the
565 * byte value. */
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +0000566 byte_mb = make_mbchar((long)byte,
567 &byte_mb_len);
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000568
569 seq = (int *)nmalloc(byte_mb_len *
570 sizeof(int));
571
572 for (i = 0; i < byte_mb_len; i++)
573 seq[i] = (unsigned char)byte_mb[i];
574
575 unget_input(seq, byte_mb_len);
576
577 free(byte_mb);
578 free(seq);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000579 }
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000580 } else {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000581 /* Reset the escape counter. */
582 escapes = 0;
583 if (byte_digits == 0)
584 /* Two escapes followed by a non-decimal
585 * digit or a decimal digit that would
586 * create a byte sequence greater than 2XX,
587 * and we're not in the middle of a byte
588 * sequence: control character sequence
589 * mode. Interpret the control sequence and
590 * save the corresponding control character
591 * as the result. */
592 retval = get_control_kbinput(*kbinput);
593 else {
594 /* If we're in the middle of a byte
595 * sequence, reset the byte sequence counter
596 * and save the character we got as the
597 * result. */
598 byte_digits = 0;
599 retval = *kbinput;
600 }
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000601 }
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000602 break;
603 }
604 }
605
David Lawrence Ramsey5f274c42006-04-28 19:27:41 +0000606 if (retval != ERR) {
607 /* If our result is NANO_CONTROL_8, translate it to either
David Lawrence Ramseyb9446ac2006-05-19 14:26:16 +0000608 * Delete or Backspace, depending on whether REBIND_DELETE is
David Lawrence Ramsey5f274c42006-04-28 19:27:41 +0000609 * TRUE or FALSE. */
610 if (retval == NANO_CONTROL_8)
David Lawrence Ramseyb9446ac2006-05-19 14:26:16 +0000611 retval = ISSET(REBIND_DELETE) ? NANO_DELETE_KEY :
612 NANO_BACKSPACE_KEY;
David Lawrence Ramsey5f274c42006-04-28 19:27:41 +0000613
614 /* If our result is an extended keypad value (i.e, a value
615 * outside of byte range), set func_key to TRUE. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000616 *func_key = !is_byte(retval);
David Lawrence Ramsey5f274c42006-04-28 19:27:41 +0000617 }
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000618
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000619#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000620 fprintf(stderr, "parse_kbinput(): kbinput = %d, meta_key = %d, func_key = %d, escapes = %d, byte_digits = %d, retval = %d\n", *kbinput, (int)*meta_key, (int)*func_key, escapes, byte_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000621#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000622
623 /* Return the result. */
624 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000625}
626
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000627/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000628 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000629 * are generated when the keypad doesn't support the needed keys. If
630 * the escape sequence is recognized but we want to ignore it, return
631 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
632 * set ignore_seq to FALSE. Assume that Escape has already been read
633 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000634int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000635 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000636{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000637 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000638
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000639 *ignore_seq = FALSE;
640
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000641 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000642 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000643 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000644 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000645 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000646 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000647 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000648 case 'P': /* Esc O 2 P == F13 on
649 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000650 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000651 break;
652 case 'Q': /* Esc O 2 Q == F14 on
653 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000654 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000655 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000656 case 'R': /* Esc O 2 R == F15 on
657 * xterm. */
658 retval = KEY_F(15);
659 break;
660 case 'S': /* Esc O 2 S == F16 on
661 * xterm. */
662 retval = KEY_F(16);
663 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000664 }
665 }
666 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000667 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
668 case 'B': /* Esc O B == Down on
669 * VT100/VT320/xterm. */
670 case 'C': /* Esc O C == Right on
671 * VT100/VT320/xterm. */
672 case 'D': /* Esc O D == Left on
673 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000674 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000675 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000676 case 'E': /* Esc O E == Center (5) on numeric keypad
677 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000678 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000679 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000680 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000681 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000682 break;
683 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000684 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000685 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000686 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000687 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000688 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000689 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000690 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000691 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000692 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000693 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000694 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000695 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000696 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000697 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000698 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000699 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000700 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000701 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000702 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000703 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000704 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000705 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000706 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000707 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000708 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000709 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000710 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000711 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000712 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000713 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000714 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000715 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000716 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000717 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000718 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000719 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000720 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000721 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000722 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000723 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000724 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000725 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000726 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000727 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000728 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000729 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000730 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000731 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000732 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000733 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000734 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000735 break;
736 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000737 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000738 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000739 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000740 break;
741 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000742 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000743 * rxvt/Eterm. */
David Lawrence Ramsey8f36d092005-09-24 19:42:48 +0000744 retval = ',';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000745 break;
746 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000747 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000748 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000749 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000750 break;
751 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000752 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000753 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000754 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000755 break;
756 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000757 * NumLock off on VT100/VT220/VT320/xterm/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000758 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000759 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000760 break;
761 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000762 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000763 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000764 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000765 break;
766 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000767 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000768 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000769 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000770 break;
771 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000772 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000773 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000774 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000775 break;
776 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000777 * keypad with NumLock off on VT100/VT220/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000778 * VT320/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000779 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000780 break;
781 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000782 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000783 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000784 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000785 break;
786 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000787 * with NumLock off on VT100/VT220/VT320/
788 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000789 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000790 break;
791 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000792 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000793 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000794 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000795 break;
796 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000797 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000798 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000799 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000800 break;
801 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000802 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000803 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000804 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000805 break;
806 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000807 * with NumLock off on VT100/VT220/VT320/
David Lawrence Ramsey28889642006-05-30 20:51:15 +0000808 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000809 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000810 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000811 }
812 break;
813 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000814 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000815 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000816 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000817 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000818 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000819 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000820 break;
821 }
822 break;
823 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000824 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000825 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000826 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000827 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000828 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
829 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000830 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000831 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000832 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
833 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000834 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000835 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000836 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
837 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000838 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000839 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000840 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
841 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000842 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000843 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000844 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
845 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000846 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000847 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000848 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000849 * VT220/VT320/Linux console/
850 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000851 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000852 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000853 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000854 * VT220/VT320/Linux console/
855 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000856 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000857 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000858 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000859 * VT220/VT320/Linux console/
860 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000861 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000862 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000863 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000864 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000865 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000866 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000867 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000868 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000869 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
870 * xterm. */
871 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
872 * xterm. */
873 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
874 * xterm. */
875 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
876 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000877 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000878 break;
879 }
880 }
881 break;
882 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000883 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000884 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000885 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
886 * xterm. */
887 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
888 * xterm. */
889 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
890 * xterm. */
891 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
892 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000893 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000894 break;
895 }
896 }
897 break;
898 }
899 }
900 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000901 default: /* Esc [ 1 ~ == Home on
902 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000903 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000904 break;
905 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000906 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000907 break;
908 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000909 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000910 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000911 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000912 * VT220/VT320/Linux console/
913 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000914 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000915 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000916 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000917 * VT220/VT320/Linux console/
918 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000919 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000920 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000921 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000922 * VT220/VT320/Linux console/
923 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000924 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000925 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000926 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000927 * VT220/VT320/Linux console/
928 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000929 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000930 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000931 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000932 * VT220/VT320/Linux console/
933 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000934 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000935 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000936 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000937 * VT220/VT320/Linux console/
938 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000939 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000940 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000941 case '8': /* Esc [ 2 8 ~ == F15 on
942 * VT220/VT320/Linux console/
943 * rxvt/Eterm. */
944 retval = KEY_F(15);
945 break;
946 case '9': /* Esc [ 2 9 ~ == F16 on
947 * VT220/VT320/Linux console/
948 * rxvt/Eterm. */
949 retval = KEY_F(16);
950 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000951 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000952 * VT220/VT320/Linux console/
953 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000954 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000955 break;
956 }
957 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000958 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000959 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
960 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000961 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000962 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000963 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000964 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000965 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000966 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000967 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
968 * Linux console/xterm; Esc [ 5 ^ ==
969 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000970 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000971 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000972 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
973 * Linux console/xterm; Esc [ 6 ^ ==
974 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000975 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000976 break;
977 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000978 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000979 break;
980 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000981 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000982 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000983 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000984 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000985 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000986 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000987 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000988 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000989 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000990 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000991 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000992 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000993 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000994 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000995 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000996 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000997 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000998 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000999 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001000 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001001 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001002 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001003 case 'E': /* Esc [ E == Center (5) on numeric keypad
1004 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +00001005 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001006 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001007 case 'F': /* Esc [ F == End on FreeBSD
1008 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001009 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001010 break;
1011 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001012 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001013 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001014 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001015 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001016 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001017 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001018 break;
1019 case 'I': /* Esc [ I == PageUp on FreeBSD
1020 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001021 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001022 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001023 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001024 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001025 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001026 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001027 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001028 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001029 break;
1030 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001031 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001032 break;
1033 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001034 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001035 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001036 case 'P': /* Esc [ O P == F1 on
1037 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001038 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001039 break;
1040 case 'Q': /* Esc [ O Q == F2 on
1041 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001042 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001043 break;
1044 case 'R': /* Esc [ O R == F3 on
1045 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001046 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001047 break;
1048 case 'S': /* Esc [ O S == F4 on
1049 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001050 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001051 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001052 }
David Lawrence Ramseyec729752005-09-25 18:42:05 +00001053 } else
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001054 /* Esc [ O == F3 on FreeBSD console. */
1055 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001056 break;
1057 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001058 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001059 break;
1060 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001062 break;
1063 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001064 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001065 break;
1066 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001067 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001068 break;
1069 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001070 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001071 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001072 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001073 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001074 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001075 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001076 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001077 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001078 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001079 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001080 break;
1081 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001082 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001083 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001084 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001085 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001086 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001087 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001088 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001089 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001090 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001091 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001092 case 'c': /* Esc [ c == Shift-Right on rxvt/
1093 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001094 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001095 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001096 break;
1097 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001098 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001099 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001100 case 'A': /* Esc [ [ A == F1 on Linux
1101 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001102 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001103 break;
1104 case 'B': /* Esc [ [ B == F2 on Linux
1105 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001106 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001107 break;
1108 case 'C': /* Esc [ [ C == F3 on Linux
1109 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001110 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001111 break;
1112 case 'D': /* Esc [ [ D == F4 on Linux
1113 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001114 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001115 break;
1116 case 'E': /* Esc [ [ E == F5 on Linux
1117 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001118 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001119 break;
1120 }
1121 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001122 break;
1123 }
1124 break;
1125 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001126 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001127
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001128#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001129 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001130#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001131
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001132 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001133}
1134
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001135/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001136 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001137 * to many escape sequences. */
1138int get_escape_seq_abcd(int kbinput)
1139{
1140 switch (tolower(kbinput)) {
1141 case 'a':
1142 return NANO_PREVLINE_KEY;
1143 case 'b':
1144 return NANO_NEXTLINE_KEY;
1145 case 'c':
1146 return NANO_FORWARD_KEY;
1147 case 'd':
1148 return NANO_BACK_KEY;
1149 default:
1150 return ERR;
1151 }
1152}
1153
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001154/* Interpret the escape sequence in the keystroke buffer, the first
David Lawrence Ramseyf1022082006-06-08 02:01:49 +00001155 * character of which is kbinput. If we want to ignore the escape
1156 * sequence, set retval to ERR and ignore_seq to TRUE. Assume that the
1157 * keystroke buffer isn't empty, and that the initial escape has already
1158 * been read in. */
1159int parse_escape_seq_kbinput(int kbinput, bool *ignore_seq)
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001160{
1161 int retval, *seq;
1162 size_t seq_len;
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001163
1164 /* Put back the non-escape character, get the complete escape
1165 * sequence, translate the sequence into its corresponding key
1166 * value, and save that as the result. */
1167 unget_input(&kbinput, 1);
1168 seq_len = get_key_buffer_len();
1169 seq = get_input(NULL, seq_len);
David Lawrence Ramseyf1022082006-06-08 02:01:49 +00001170 retval = get_escape_seq_kbinput(seq, seq_len, ignore_seq);
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001171
1172 free(seq);
1173
1174#ifdef DEBUG
David Lawrence Ramsey1d60d782006-06-08 16:56:00 +00001175 fprintf(stderr, "parse_escape_seq_kbinput(): kbinput = %d, ignore_seq = %d, seq_len = %lu, retval = %d\n", kbinput, (int)*ignore_seq, (unsigned long)seq_len, retval);
David Lawrence Ramsey1320d292006-05-25 22:10:27 +00001176#endif
1177
1178 return retval;
1179}
1180
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001181/* Translate a byte sequence: turn a three-digit decimal number (from
1182 * 000 to 255) into its corresponding byte value. */
David Lawrence Ramseyfc0f8f82006-05-10 13:41:53 +00001183int get_byte_kbinput(int kbinput)
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001184{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001185 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001186 int retval = ERR;
1187
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001188 /* Increment the byte digit counter. */
1189 byte_digits++;
1190
1191 switch (byte_digits) {
1192 case 1:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001193 /* First digit: This must be from zero to two. Put it in
1194 * the 100's position of the byte sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001195 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001196 byte = (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001197 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001198 /* This isn't the start of a byte sequence. Return this
1199 * character as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001200 retval = kbinput;
1201 break;
1202 case 2:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001203 /* Second digit: This must be from zero to five if the first
1204 * was two, and may be any decimal value if the first was
1205 * zero or one. Put it in the 10's position of the byte
1206 * sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001207 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1208 '6' <= kbinput && kbinput <= '9'))
1209 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001210 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001211 /* This isn't the second digit of a byte sequence.
1212 * Return this character as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001213 retval = kbinput;
1214 break;
1215 case 3:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001216 /* Third digit: This must be from zero to five if the first
1217 * was two and the second was between zero and five, and may
1218 * be any decimal value if the first was zero or one and the
1219 * second was between six and nine. Put it in the 1's
1220 * position of the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001221 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1222 '6' <= kbinput && kbinput <= '9')) {
David Lawrence Ramsey28889642006-05-30 20:51:15 +00001223 byte += kbinput - '0';
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001224 /* If this character is a valid decimal value, then the
1225 * byte sequence is complete. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001226 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001227 } else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001228 /* This isn't the third digit of a byte sequence.
1229 * Return this character as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001230 retval = kbinput;
1231 break;
1232 default:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001233 /* If there are more than three digits, return this
1234 * character as the result. (Maybe we should produce an
1235 * error instead?) */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001236 retval = kbinput;
1237 break;
1238 }
1239
1240 /* If we have a result, reset the byte digit counter and the byte
1241 * sequence holder. */
1242 if (retval != ERR) {
1243 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001244 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001245 }
1246
1247#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001248 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 +00001249#endif
1250
1251 return retval;
1252}
1253
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001254#ifdef ENABLE_UTF8
David Lawrence Ramsey7f1b1192006-05-28 17:30:28 +00001255/* If the character in kbinput is a valid hexadecimal digit, multiply it
1256 * by factor and add the result to uni. */
1257long add_unicode_digit(int kbinput, long factor, long *uni)
1258{
1259 long retval = ERR;
1260
1261 if ('0' <= kbinput && kbinput <= '9')
1262 *uni += (kbinput - '0') * factor;
1263 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
1264 *uni += (tolower(kbinput) - 'a' + 10) * factor;
1265 else
1266 /* If this character isn't a valid hexadecimal value, save it as
1267 * the result. */
1268 retval = kbinput;
1269
1270 return retval;
1271}
1272
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001273/* Translate a Unicode sequence: turn a six-digit hexadecimal number
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001274 * (from 000000 to 10FFFF, case-insensitive) into its corresponding
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001275 * multibyte value. */
David Lawrence Ramseyfc0f8f82006-05-10 13:41:53 +00001276long get_unicode_kbinput(int kbinput)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001277{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001278 static int uni_digits = 0;
1279 static long uni = 0;
1280 long retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001281
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001282 /* Increment the Unicode digit counter. */
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001283 uni_digits++;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001284
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001285 switch (uni_digits) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001286 case 1:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001287 /* First digit: This must be zero or one. Put it in the
1288 * 0x100000's position of the Unicode sequence holder. */
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001289 if ('0' <= kbinput && kbinput <= '1')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001290 uni = (kbinput - '0') * 0x100000;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001291 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001292 /* This isn't the first digit of a Unicode sequence.
1293 * Return this character as the result. */
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001294 retval = kbinput;
1295 break;
1296 case 2:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001297 /* Second digit: This must be zero if the first was one, and
1298 * may be any hexadecimal value if the first was zero. Put
1299 * it in the 0x10000's position of the Unicode sequence
1300 * holder. */
1301 if (uni == 0 || '0' == kbinput)
1302 retval = add_unicode_digit(kbinput, 0x10000, &uni);
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001303 else
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001304 /* This isn't the second digit of a Unicode sequence.
1305 * Return this character as the result. */
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001306 retval = kbinput;
1307 break;
1308 case 3:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001309 /* Third digit: This may be any hexadecimal value. Put it
1310 * in the 0x1000's position of the Unicode sequence
1311 * holder. */
1312 retval = add_unicode_digit(kbinput, 0x1000, &uni);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001313 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001314 case 4:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001315 /* Fourth digit: This may be any hexadecimal value. Put it
1316 * in the 0x100's position of the Unicode sequence
1317 * holder. */
1318 retval = add_unicode_digit(kbinput, 0x100, &uni);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001319 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001320 case 5:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001321 /* Fifth digit: This may be any hexadecimal value. Put it
1322 * in the 0x10's position of the Unicode sequence holder. */
1323 retval = add_unicode_digit(kbinput, 0x10, &uni);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001324 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001325 case 6:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001326 /* Sixth digit: This may be any hexadecimal value. Put it
1327 * in the 0x1's position of the Unicode sequence holder. */
1328 retval = add_unicode_digit(kbinput, 0x1, &uni);
1329 /* If this character is a valid hexadecimal value, then the
1330 * Unicode sequence is complete. */
1331 if (retval == ERR)
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001332 retval = uni;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001333 break;
1334 default:
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001335 /* If there are more than six digits, return this character
1336 * as the result. (Maybe we should produce an error
1337 * instead?) */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001338 retval = kbinput;
1339 break;
1340 }
1341
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001342 /* If we have a result, reset the Unicode digit counter and the
1343 * Unicode sequence holder. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001344 if (retval != ERR) {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001345 uni_digits = 0;
1346 uni = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001347 }
1348
1349#ifdef DEBUG
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001350 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 +00001351#endif
1352
1353 return retval;
1354}
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001355#endif /* ENABLE_UTF8 */
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001356
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001357/* Translate a control character sequence: turn an ASCII non-control
1358 * character into its corresponding control character. */
1359int get_control_kbinput(int kbinput)
1360{
1361 int retval;
1362
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001363 /* Ctrl-Space (Ctrl-2, Ctrl-@, Ctrl-`) */
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001364 if (kbinput == ' ' || kbinput == '2')
1365 retval = NANO_CONTROL_SPACE;
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001366 /* Ctrl-/ (Ctrl-7, Ctrl-_) */
1367 else if (kbinput == '/')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001368 retval = NANO_CONTROL_7;
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001369 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-/, Ctrl-_) */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001370 else if ('3' <= kbinput && kbinput <= '7')
1371 retval = kbinput - 24;
1372 /* Ctrl-8 (Ctrl-?) */
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001373 else if (kbinput == '8' || kbinput == '?')
1374 retval = NANO_CONTROL_8;
David Lawrence Ramsey51cb7fd2006-05-20 17:19:09 +00001375 /* Ctrl-@ (Ctrl-Space, Ctrl-2, Ctrl-`) to Ctrl-_ (Ctrl-/, Ctrl-7) */
1376 else if ('@' <= kbinput && kbinput <= '_')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001377 retval = kbinput - '@';
David Lawrence Ramsey4d9ef692006-04-28 18:26:07 +00001378 /* Ctrl-` (Ctrl-2, Ctrl-Space, Ctrl-@) to Ctrl-~ (Ctrl-6, Ctrl-^) */
1379 else if ('`' <= kbinput && kbinput <= '~')
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001380 retval = kbinput - '`';
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001381 else
1382 retval = kbinput;
1383
1384#ifdef DEBUG
1385 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1386#endif
1387
1388 return retval;
1389}
1390
David Lawrence Ramsey561db3a2006-05-26 03:22:44 +00001391/* Put the output-formatted characters in output back into the keystroke
1392 * buffer, so that they can be parsed and displayed as output again. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001393void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001394{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001395 int *input;
1396 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001397
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001398 if (output_len == 0)
1399 return;
1400
1401 input = (int *)nmalloc(output_len * sizeof(int));
1402 for (i = 0; i < output_len; i++)
1403 input[i] = (int)output[i];
1404 unget_input(input, output_len);
1405 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001406}
1407
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001408/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001409 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1410int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1411{
1412 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001413
1414 /* Turn off flow control characters if necessary so that we can type
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001415 * them in verbatim, and turn the keypad off if necessary so that we
1416 * don't get extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001417 if (ISSET(PRESERVE))
1418 disable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001419 if (!ISSET(REBIND_KEYPAD))
1420 keypad(win, FALSE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001421
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001422 /* Read in a stream of characters and interpret it if possible. */
1423 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001424
1425 /* Turn flow control characters back on if necessary and turn the
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001426 * keypad back on if necessary now that we're done. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001427 if (ISSET(PRESERVE))
1428 enable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001429 if (!ISSET(REBIND_KEYPAD))
1430 keypad(win, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001431
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001432 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001433}
1434
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001435/* Read in a stream of all available characters, and return the length
1436 * of the string in kbinput_len. Translate the first few characters of
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001437 * the input into the corresponding multibyte value if possible. After
1438 * that, leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001439int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001440{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001441 int *kbinput, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001442
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001443 /* Read in the first keystroke. */
1444 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001445
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001446#ifdef ENABLE_UTF8
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001447 if (using_utf8()) {
1448 /* Check whether the first keystroke is a valid hexadecimal
1449 * digit. */
David Lawrence Ramseya5b1ca22006-05-28 17:09:49 +00001450 long uni = get_unicode_kbinput(*kbinput);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001451
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001452 /* If the first keystroke isn't a valid hexadecimal digit, put
1453 * back the first keystroke. */
1454 if (uni != ERR)
1455 unget_input(kbinput, 1);
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001456
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001457 /* Otherwise, read in keystrokes until we have a complete
1458 * Unicode sequence, and put back the corresponding Unicode
1459 * value. */
1460 else {
1461 char *uni_mb;
1462 int uni_mb_len, *seq, i;
David Lawrence Ramsey6fb66892006-05-27 17:39:19 +00001463
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001464 if (win == edit)
1465 /* TRANSLATORS: This is displayed during the input of a
1466 * six-digit hexadecimal Unicode character code. */
1467 statusbar(_("Unicode Input"));
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001468
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001469 while (uni == ERR) {
1470 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey12e37082006-05-27 15:52:26 +00001471
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001472 uni = get_unicode_kbinput(*kbinput);
1473 }
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001474
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001475 /* Put back the multibyte equivalent of the Unicode
1476 * value. */
1477 uni_mb = make_mbchar(uni, &uni_mb_len);
1478
1479 seq = (int *)nmalloc(uni_mb_len * sizeof(int));
1480
1481 for (i = 0; i < uni_mb_len; i++)
1482 seq[i] = (unsigned char)uni_mb[i];
1483
1484 unget_input(seq, uni_mb_len);
1485
1486 free(seq);
1487 free(uni_mb);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001488 }
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001489 } else
David Lawrence Ramseya5b1ca22006-05-28 17:09:49 +00001490#endif /* ENABLE_UTF8 */
1491
David Lawrence Ramsey5c7d88d2006-05-28 16:25:15 +00001492 /* Put back the first keystroke. */
1493 unget_input(kbinput, 1);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001494
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001495 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001496 * result. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00001497 *kbinput_len = get_key_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001498 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001499
1500 return retval;
1501}
1502
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001503#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001504/* Check for a mouse event, and if one's taken place, save the
1505 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001506 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1507 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001508 * place on it, figure out which shortcut was clicked and put back the
1509 * equivalent keystroke(s). Return FALSE if no keystrokes were
1510 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001511 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001512bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001513{
1514 MEVENT mevent;
1515
1516 *mouse_x = -1;
1517 *mouse_y = -1;
1518
1519 /* First, get the actual mouse event. */
1520 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001521 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001522
David Lawrence Ramsey865ad942006-06-29 01:38:58 +00001523 /* If it's not a release or click of the first mouse button, get
1524 * out. */
1525 if (!(mevent.bstate & (BUTTON1_RELEASED | BUTTON1_CLICKED)))
David Lawrence Ramsey98e4d4f2006-06-28 21:54:55 +00001526 return FALSE;
1527
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001528 /* Save the screen coordinates where the mouse event took place. */
1529 *mouse_x = mevent.x;
1530 *mouse_y = mevent.y;
1531
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001532 /* If we're allowing shortcuts, the current shortcut list is being
1533 * displayed on the last two lines of the screen, and the mouse
1534 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001535 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001536 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1537 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001538 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001539 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001540 /* The number of shortcuts in the current shortcut list. */
1541 const shortcut *s = currshortcut;
1542 /* The actual shortcut we clicked on, starting at the first
1543 * one in the current shortcut list. */
1544
1545 /* Get the shortcut lists' length. */
1546 if (currshortcut == main_list)
1547 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001548 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001549 currslen = length_of_list(currshortcut);
1550
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001551 /* We don't show any more shortcuts than the main list
1552 * does. */
1553 if (currslen > MAIN_VISIBLE)
1554 currslen = MAIN_VISIBLE;
1555 }
1556
David Lawrence Ramseye806ab82006-04-18 16:13:35 +00001557 /* Calculate the width of all of the shortcuts in the list
1558 * except for the last two, which are longer by (COLS % i)
1559 * columns so as to not waste space. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001560 if (currslen < 2)
David Lawrence Ramseye806ab82006-04-18 16:13:35 +00001561 i = COLS / (MAIN_VISIBLE / 2);
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001562 else
1563 i = COLS / ((currslen / 2) + (currslen % 2));
1564
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001565 /* Calculate the y-coordinate relative to the beginning of
David Lawrence Ramseyf7260532005-10-28 17:12:58 +00001566 * the shortcut list in bottomwin, i.e, with the sizes of
1567 * topwin, edit, and the first line of bottomwin subtracted
David Lawrence Ramseye806ab82006-04-18 16:13:35 +00001568 * out, and set j to it. */
David Lawrence Ramseyf7260532005-10-28 17:12:58 +00001569 j = *mouse_y - (2 - no_more_space()) - editwinrows - 1;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001570
David Lawrence Ramseye806ab82006-04-18 16:13:35 +00001571 /* If we're on the statusbar, don't do anything. */
1572 if (j < 0)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001573 return FALSE;
David Lawrence Ramseye806ab82006-04-18 16:13:35 +00001574
1575 /* Calculate the x-coordinate relative to the beginning of the
1576 * shortcut list in bottomwin, and add it to j. j should now be
1577 * the index in the shortcut list of the shortcut we clicked. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001578 j = (*mouse_x / i) * 2 + j;
David Lawrence Ramseye806ab82006-04-18 16:13:35 +00001579
1580 /* Adjust j if we clicked in the last two shortcuts. */
1581 if ((j >= currslen) && (*mouse_x % i < COLS % i))
1582 j -= 2;
1583
1584 /* If we're beyond the last shortcut, don't do anything. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001585 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001586 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001587
1588 /* Go through the shortcut list to determine which shortcut was
1589 * clicked. */
1590 for (; j > 0; j--)
1591 s = s->next;
1592
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001593 /* And put back the equivalent key. Assume that each shortcut
1594 * has, at the very least, an equivalent control key, an
1595 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001596 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001597 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001598 return TRUE;
1599 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001600 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001601 return TRUE;
1602 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001603 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001604 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001605}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001606#endif /* !DISABLE_MOUSE */
1607
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001608/* Return the shortcut corresponding to the values of kbinput (the key
1609 * itself), meta_key (whether the key is a meta sequence), and func_key
1610 * (whether the key is a function key), if any. The shortcut will be
1611 * the first one in the list (control key, meta key sequence, function
1612 * key, other meta key sequence) for the corresponding function. For
1613 * example, passing in a meta key sequence that corresponds to a
1614 * function with a control key, a function key, and a meta key sequence
1615 * will return the control key corresponding to that function. */
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001616const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001617 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001618{
1619 const shortcut *s = s_list;
1620 size_t slen = length_of_list(s_list);
1621
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001622#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001623 fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %d, func_key = %d\n", *kbinput, (int)*meta_key, (int)*func_key);
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001624#endif
1625
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001626 /* Check for shortcuts. */
1627 for (; slen > 0; slen--) {
1628 /* We've found a shortcut if:
1629 *
1630 * 1. The key exists.
1631 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001632 * 3. meta_key is TRUE and the key is the primary or
1633 * miscellaneous meta sequence in the shortcut list.
1634 * 4. func_key is TRUE and the key is a function key in the
1635 * shortcut list. */
1636
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001637 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1638 (*meta_key == TRUE && (*kbinput == s->metaval ||
1639 *kbinput == s->miscval)) || (*func_key == TRUE &&
1640 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001641 break;
1642 }
1643
1644 s = s->next;
1645 }
1646
1647 /* Translate the shortcut to either its control key or its meta key
1648 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001649 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001650 if (slen > 0) {
1651 if (s->ctrlval != NANO_NO_KEY) {
1652 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001653 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001654 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001655 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001656 } else if (s->metaval != NANO_NO_KEY) {
1657 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001658 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001659 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001660 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001661 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001662 }
1663
1664 return NULL;
1665}
1666
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001667#ifndef NANO_TINY
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001668/* Return the global toggle corresponding to the values of kbinput (the
1669 * key itself) and meta_key (whether the key is a meta sequence), if
1670 * any. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001671const toggle *get_toggle(int kbinput, bool meta_key)
1672{
1673 const toggle *t = toggles;
1674
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001675#ifdef DEBUG
1676 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1677#endif
1678
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001679 /* Check for toggles. */
1680 for (; t != NULL; t = t->next) {
David Lawrence Ramseye313f5b2006-04-20 22:29:02 +00001681 /* We've found a toggle if the key exists, meta_key is TRUE, and
1682 * the key is in the meta key toggle list. */
David Lawrence Ramsey1df3e2d2006-04-22 19:45:26 +00001683 if (t->val != TOGGLE_NO_KEY && meta_key && kbinput == t->val)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001684 break;
1685 }
1686
1687 return t;
1688}
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001689#endif /* !NANO_TINY */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001690
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001691/* Move to (x, y) in win, and display a line of n spaces with the
1692 * current attributes. */
1693void blank_line(WINDOW *win, int y, int x, int n)
1694{
1695 wmove(win, y, x);
1696 for (; n > 0; n--)
1697 waddch(win, ' ');
1698}
1699
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001700/* Blank the first line of the top portion of the window. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001701void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001702{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001703 blank_line(topwin, 0, 0, COLS);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001704}
1705
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001706/* If the MORE_SPACE flag isn't set, blank the second line of the top
1707 * portion of the window. */
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00001708void blank_topbar(void)
1709{
1710 if (!ISSET(MORE_SPACE))
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001711 blank_line(topwin, 1, 0, COLS);
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00001712}
1713
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001714/* Blank all the lines of the middle portion of the window, i.e, the
1715 * edit window. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001716void blank_edit(void)
1717{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001718 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001719 for (i = 0; i < editwinrows; i++)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001720 blank_line(edit, i, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001721}
1722
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001723/* Blank the first line of the bottom portion of the window. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001724void blank_statusbar(void)
1725{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001726 blank_line(bottomwin, 0, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001727}
1728
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001729/* If the NO_HELP flag isn't set, blank the last two lines of the bottom
1730 * portion of the window. */
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00001731void blank_bottombars(void)
1732{
1733 if (!ISSET(NO_HELP)) {
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001734 blank_line(bottomwin, 1, 0, COLS);
1735 blank_line(bottomwin, 2, 0, COLS);
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00001736 }
1737}
1738
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00001739/* Check if the number of keystrokes needed to blank the statusbar has
1740 * been pressed. If so, blank the statusbar, unless constant cursor
1741 * position display is on. */
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001742void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001743{
David Lawrence Ramsey100bc302006-05-27 18:06:11 +00001744 if (statusblank > 0) {
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001745 statusblank--;
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00001746
David Lawrence Ramsey100bc302006-05-27 18:06:11 +00001747 if (statusblank == 0 && !ISSET(CONST_UPDATE)) {
1748 blank_statusbar();
1749 wnoutrefresh(bottomwin);
1750 reset_cursor();
1751 wnoutrefresh(edit);
1752 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001753 }
1754}
1755
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001756/* Convert buf into a string that can be displayed on screen. The
1757 * caller wants to display buf starting with column start_col, and
1758 * extending for at most len columns. start_col is zero-based. len is
1759 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001760 * string is dynamically allocated, and should be freed. If dollars is
1761 * TRUE, the caller might put "$" at the beginning or end of the line if
1762 * it's too long. */
1763char *display_string(const char *buf, size_t start_col, size_t len, bool
1764 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001765{
1766 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00001767 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001768 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00001769 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001770 size_t alloc_len;
1771 /* The length of memory allocated for converted. */
1772 char *converted;
1773 /* The string we return. */
1774 size_t index;
1775 /* Current position in converted. */
David Lawrence Ramsey1f104f82006-02-03 03:51:51 +00001776 char *buf_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001777 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001778
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00001779 /* If dollars is TRUE, make room for the "$" at the end of the
1780 * line. */
1781 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
1782 len--;
1783
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001784 if (len == 0)
1785 return mallocstrcpy(NULL, "");
1786
David Lawrence Ramsey1f104f82006-02-03 03:51:51 +00001787 buf_mb = charalloc(mb_cur_max());
1788
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001789 start_index = actual_x(buf, start_col);
1790 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001791
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001792 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001793
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001794 /* Make sure there's enough room for the initial character, whether
1795 * it's a multibyte control character, a non-control multibyte
1796 * character, a tab character, or a null terminator. Rationale:
1797 *
1798 * multibyte control character followed by a null terminator:
1799 * 1 byte ('^') + mb_cur_max() bytes + 1 byte ('\0')
1800 * multibyte non-control character followed by a null terminator:
1801 * mb_cur_max() bytes + 1 byte ('\0')
1802 * tab character followed by a null terminator:
1803 * mb_cur_max() bytes + (tabsize - 1) bytes + 1 byte ('\0')
1804 *
1805 * Since tabsize has a minimum value of 1, it can substitute for 1
1806 * byte above. */
1807 alloc_len = (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
1808 converted = charalloc(alloc_len);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00001809
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001810 index = 0;
1811
David Lawrence Ramsey567d4712006-07-05 05:31:21 +00001812 if (buf[start_index] != '\0' && buf[start_index] != '\t' &&
1813 (column < start_col || (dollars && column > 0))) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001814 /* We don't display all of buf[start_index] since it starts to
1815 * the left of the screen. */
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001816 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001817
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001818 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00001819 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001820 char *ctrl_buf_mb = charalloc(mb_cur_max());
1821 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001822
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001823 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
1824 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00001825
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001826 for (i = 0; i < ctrl_buf_mb_len; i++)
1827 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001828
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001829 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001830
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001831 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00001832
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001833 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001834 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00001835 }
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00001836#ifdef ENABLE_UTF8
David Lawrence Ramseyd99b0e12006-05-19 17:50:01 +00001837 else if (using_utf8() && mbwidth(buf_mb) == 2) {
1838 if (column >= start_col) {
1839 converted[index++] = ' ';
1840 start_col++;
1841 }
1842
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00001843 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00001844 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001845
1846 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001847 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00001848#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001849 }
1850
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001851 while (buf[start_index] != '\0') {
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001852 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001853
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001854 /* Make sure there's enough room for the next character, whether
1855 * it's a multibyte control character, a non-control multibyte
1856 * character, a tab character, or a null terminator. */
1857 if (index + mb_cur_max() + tabsize + 1 >= alloc_len - 1) {
1858 alloc_len += (mb_cur_max() + tabsize + 1) * MAX_BUF_SIZE;
1859 converted = charealloc(converted, alloc_len);
1860 }
1861
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00001862 /* If buf contains a tab character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001863 if (*buf_mb == '\t') {
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001864#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001865 if (ISSET(WHITESPACE_DISPLAY)) {
1866 int i;
1867
1868 for (i = 0; i < whitespace_len[0]; i++)
1869 converted[index++] = whitespace[i];
1870 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001871#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001872 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001873 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00001874 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001875 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001876 start_col++;
1877 }
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001878 /* If buf contains a control character, interpret it. If buf
David Lawrence Ramsey61f56732005-07-21 22:12:03 +00001879 * contains an invalid multibyte control character, display it
1880 * as such.*/
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001881 } else if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001882 char *ctrl_buf_mb = charalloc(mb_cur_max());
1883 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001884
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001885 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001886 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001887
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001888 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
1889 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001890
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001891 for (i = 0; i < ctrl_buf_mb_len; i++)
1892 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001893
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001894 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001895
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001896 free(ctrl_buf_mb);
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00001897 /* If buf contains a space character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001898 } else if (*buf_mb == ' ') {
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00001899#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001900 if (ISSET(WHITESPACE_DISPLAY)) {
1901 int i;
1902
1903 for (i = whitespace_len[0]; i < whitespace_len[0] +
1904 whitespace_len[1]; i++)
1905 converted[index++] = whitespace[i];
1906 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001907#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001908 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001909 start_col++;
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001910 /* If buf contains a non-control character, interpret it. If
1911 * buf contains an invalid multibyte non-control character,
1912 * display it as such. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001913 } else {
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001914 char *nctrl_buf_mb = charalloc(mb_cur_max());
1915 int nctrl_buf_mb_len, i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001916
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001917 nctrl_buf_mb = mbrep(buf_mb, nctrl_buf_mb,
1918 &nctrl_buf_mb_len);
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001919
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001920 for (i = 0; i < nctrl_buf_mb_len; i++)
1921 converted[index++] = nctrl_buf_mb[i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001922
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001923 start_col += mbwidth(nctrl_buf_mb);
1924
1925 free(nctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001926 }
1927
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001928 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001929 }
1930
David Lawrence Ramsey6a0d5b82005-06-13 14:00:22 +00001931 free(buf_mb);
1932
David Lawrence Ramsey114cfb62006-02-03 03:58:49 +00001933 assert(alloc_len >= index + 1);
1934
1935 /* Null terminate converted. */
1936 converted[index] = '\0';
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00001937
1938 /* Make sure converted takes up no more than len columns. */
1939 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001940 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00001941
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001942 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001943}
1944
David Lawrence Ramsey4ea2eac2006-07-09 00:52:16 +00001945/* If path is NULL, we're in normal editing mode, so display the current
1946 * version of nano, the current filename, and whether the current file
1947 * has been modified on the titlebar. If path isn't NULL, we're in the
1948 * file browser, and path contains the directory to start the file
1949 * browser in, so display the current version of nano and the contents
1950 * of path on the titlebar. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00001951void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001952{
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001953 int space = COLS;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001954 /* The space we have available for display. */
David Lawrence Ramsey3c43d3d2006-03-30 01:18:29 +00001955 size_t verlen = strlenpt(PACKAGE_STRING) + 1;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001956 /* The length of the version message in columns, plus one for
1957 * padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001958 const char *prefix;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001959 /* "DIR:", "File:", or "New Buffer". Goes before filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001960 size_t prefixlen;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001961 /* The length of the prefix in columns, plus one for padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001962 const char *state;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001963 /* "Modified", "View", or "". Shows the state of this
1964 * buffer. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001965 size_t statelen = 0;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001966 /* The length of the state in columns, or the length of
David Lawrence Ramsey4ea2eac2006-07-09 00:52:16 +00001967 * "Modified" if the state is blank and we're not in the file
1968 * browser. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001969 char *exppath = NULL;
David Lawrence Ramsey345a5b82006-07-04 03:47:36 +00001970 /* The filename, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001971 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001972 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001973 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001974 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001975
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00001976 assert(path != NULL || openfile->filename != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001977
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00001978 wattron(topwin, reverse_attr);
David Lawrence Ramsey85ffaee2006-07-02 18:29:49 +00001979
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001980 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001981
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001982 /* space has to be at least 4: two spaces before the version message,
1983 * at least one character of the version message, and one space
1984 * after the version message. */
1985 if (space < 4)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001986 space = 0;
1987 else {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001988 /* Limit verlen to 1/3 the length of the screen in columns,
1989 * minus three columns for spaces. */
1990 if (verlen > (COLS / 3) - 3)
1991 verlen = (COLS / 3) - 3;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001992 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001993
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001994 if (space >= 4) {
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00001995 /* Add a space after the version message, and account for both
1996 * it and the two spaces before it. */
David Lawrence Ramsey3c43d3d2006-03-30 01:18:29 +00001997 mvwaddnstr(topwin, 0, 2, PACKAGE_STRING,
1998 actual_x(PACKAGE_STRING, verlen));
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001999 verlen += 3;
2000
2001 /* Account for the full length of the version message. */
2002 space -= verlen;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002003 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002004
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002005#ifndef DISABLE_BROWSER
2006 /* Don't display the state if we're in the file browser. */
2007 if (path != NULL)
2008 state = "";
2009 else
2010#endif
2011 state = openfile->modified ? _("Modified") : ISSET(VIEW_MODE) ?
2012 _("View") : "";
2013
David Lawrence Ramseye3281692006-07-09 00:50:23 +00002014 statelen = strlenpt((state[0] == '\0' && path == NULL) ?
2015 _("Modified") : state);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002016
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002017 /* If possible, add a space before state. */
2018 if (space > 0 && statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002019 statelen++;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002020 else
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002021 goto the_end;
2022
2023#ifndef DISABLE_BROWSER
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002024 /* path should be a directory if we're in the file browser. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002025 if (path != NULL)
2026 prefix = _("DIR:");
2027 else
2028#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002029 if (openfile->filename[0] == '\0') {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002030 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002031 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002032 } else
2033 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002034
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002035 prefixlen = strnlenpt(prefix, space - statelen) + 1;
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002036
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002037 /* If newfie is FALSE, add a space after prefix. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002038 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002039 prefixlen++;
2040
David Lawrence Ramsey4ea2eac2006-07-09 00:52:16 +00002041 /* If we're not in the file browser, set path to the current
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002042 * filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002043 if (path == NULL)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002044 path = openfile->filename;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002045
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002046 /* Account for the full lengths of the prefix and the state. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002047 if (space >= prefixlen + statelen)
2048 space -= prefixlen + statelen;
2049 else
2050 space = 0;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002051 /* space is now the room we have for the filename. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002052
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002053 if (!newfie) {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002054 size_t lenpt = strlenpt(path), start_col;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002055
David Lawrence Ramseyc284e1d2006-07-07 16:21:45 +00002056 /* Don't set dots to TRUE if we have fewer than 8 columns (i.e,
2057 * 1 column for padding, plus 7 columns for a filename). */
David Lawrence Ramseyd59c4232006-07-08 21:23:53 +00002058 dots = (space >= 8 && lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002059
2060 if (dots) {
2061 start_col = lenpt - space + 3;
2062 space -= 3;
2063 } else
2064 start_col = 0;
2065
2066 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002067 }
2068
David Lawrence Ramsey85ffaee2006-07-02 18:29:49 +00002069 /* If dots is TRUE, we will display something like "File:
2070 * ...ename". */
2071 if (dots) {
2072 mvwaddnstr(topwin, 0, verlen - 1, prefix, actual_x(prefix,
2073 prefixlen));
2074 if (space <= -3 || newfie)
2075 goto the_end;
2076 waddch(topwin, ' ');
2077 waddnstr(topwin, "...", space + 3);
2078 if (space <= 0)
2079 goto the_end;
2080 waddstr(topwin, exppath);
2081 } else {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002082 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2083 /* The length of the expanded filename. */
2084
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002085 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002086 mvwaddnstr(topwin, 0, verlen + ((space - exppathlen) / 3),
2087 prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002088 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002089 waddch(topwin, ' ');
2090 waddstr(topwin, exppath);
2091 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002092 }
2093
2094 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002095 free(exppath);
2096
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002097 if (state[0] != '\0') {
David Lawrence Ramsey3d12f0f2005-10-26 23:14:59 +00002098 if (statelen >= COLS - 1)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002099 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
2100 else {
David Lawrence Ramseycaa86592005-07-10 23:57:32 +00002101 assert(COLS - statelen - 1 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002102
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002103 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002104 actual_x(state, statelen));
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002105 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002106 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002107
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002108 wattroff(topwin, reverse_attr);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002109
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002110 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002111 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002112 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002113}
2114
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002115/* Mark the current file as modified if it isn't already, and then
2116 * update the titlebar to display the file's new status. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002117void set_modified(void)
2118{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002119 if (!openfile->modified) {
2120 openfile->modified = TRUE;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002121 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002122 }
2123}
2124
David Lawrence Ramsey5593e202005-06-28 19:49:15 +00002125/* Display a message on the statusbar, and set disable_cursorpos to
2126 * TRUE, so that the message won't be immediately overwritten if
2127 * constant cursor position display is on. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002128void statusbar(const char *msg, ...)
2129{
2130 va_list ap;
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002131 char *bar, *foo;
2132 size_t start_x, foo_len;
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002133#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002134 bool old_whitespace;
2135#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002136
2137 va_start(ap, msg);
2138
2139 /* Curses mode is turned off. If we use wmove() now, it will muck
2140 * up the terminal settings. So we just use vfprintf(). */
David Lawrence Ramseyf70f67b2006-06-03 17:31:52 +00002141 if (isendwin()) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002142 vfprintf(stderr, msg, ap);
2143 va_end(ap);
2144 return;
2145 }
2146
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002147 blank_statusbar();
2148
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002149#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002150 old_whitespace = ISSET(WHITESPACE_DISPLAY);
2151 UNSET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002152#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002153 bar = charalloc(mb_cur_max() * (COLS - 3));
2154 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
2155 va_end(ap);
2156 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002157#if !defined(NANO_TINY) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002158 if (old_whitespace)
2159 SET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002160#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002161 free(bar);
2162 foo_len = strlenpt(foo);
2163 start_x = (COLS - foo_len - 4) / 2;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002164
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002165 wmove(bottomwin, 0, start_x);
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002166 wattron(bottomwin, reverse_attr);
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002167 waddstr(bottomwin, "[ ");
2168 waddstr(bottomwin, foo);
2169 free(foo);
2170 waddstr(bottomwin, " ]");
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002171 wattroff(bottomwin, reverse_attr);
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002172 wnoutrefresh(bottomwin);
2173 reset_cursor();
2174 wnoutrefresh(edit);
2175 /* Leave the cursor at its position in the edit window, not in
2176 * the statusbar. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002177
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002178 disable_cursorpos = TRUE;
David Lawrence Ramseyc6618532005-06-17 22:33:15 +00002179
2180 /* If we're doing quick statusbar blanking, and constant cursor
2181 * position display is off, blank the statusbar after only one
David Lawrence Ramseyce862362006-05-21 21:23:21 +00002182 * keystroke. Otherwise, blank it after twenty-six keystrokes, as
2183 * Pico does. */
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002184 statusblank =
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002185#ifndef NANO_TINY
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002186 ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 :
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002187#endif
David Lawrence Ramseyce862362006-05-21 21:23:21 +00002188 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002189}
2190
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002191/* Display the shortcut list in s on the last two rows of the bottom
2192 * portion of the window. */
Chris Allegretta6232d662002-05-12 19:52:15 +00002193void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002194{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002195 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002196
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002197 if (ISSET(NO_HELP))
2198 return;
2199
Chris Allegretta6232d662002-05-12 19:52:15 +00002200 if (s == main_list) {
2201 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002202
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002203 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002204 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002205 slen = length_of_list(s);
2206
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002207 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002208 if (slen > MAIN_VISIBLE)
2209 slen = MAIN_VISIBLE;
2210 }
2211
David Lawrence Ramseye806ab82006-04-18 16:13:35 +00002212 /* There will be this many characters per column, except for the
2213 * last two, which will be longer by (COLS % colwidth) columns so as
2214 * to not waste space. We need at least three columns to display
2215 * anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002216 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002217
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002218 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002219
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002220 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002221 const char *keystr;
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002222 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002223
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002224 /* Yucky sentinel values that we can't handle a better way. */
2225 if (s->ctrlval == NANO_CONTROL_SPACE)
2226 strcpy(foo, "^ ");
2227 else if (s->ctrlval == NANO_CONTROL_8)
2228 strcpy(foo, "^?");
2229 /* Normal values. Assume that the shortcut has an equivalent
2230 * control key, meta key sequence, or both. */
2231 else if (s->ctrlval != NANO_NO_KEY)
2232 sprintf(foo, "^%c", s->ctrlval + 64);
2233 else if (s->metaval != NANO_NO_KEY)
2234 sprintf(foo, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00002235
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002236 keystr = foo;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002237
2238 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseye806ab82006-04-18 16:13:35 +00002239 onekey(keystr, s->desc, colwidth + (COLS % colwidth));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002240 }
2241
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002242 wnoutrefresh(bottomwin);
2243 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002244 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002245}
2246
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002247/* Write a shortcut key to the help area at the bottom of the window.
2248 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2249 * to write at most len characters, even if len is very small and
2250 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2251 * the whole string! We do not bother padding the entry with blanks. */
2252void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002253{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002254 size_t keystroke_len = strlenpt(keystroke) + 1;
2255
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002256 assert(keystroke != NULL && desc != NULL);
2257
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002258 wattron(bottomwin, reverse_attr);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002259 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002260 wattroff(bottomwin, reverse_attr);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002261
2262 if (len > keystroke_len)
2263 len -= keystroke_len;
2264 else
2265 len = 0;
2266
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002267 if (len > 0) {
2268 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002269 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002270 }
2271}
2272
David Lawrence Ramsey2b9d6a02005-11-01 17:45:31 +00002273/* Reset current_y, based on the position of current, and put the cursor
2274 * in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002275void reset_cursor(void)
2276{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002277 /* If we haven't opened any files yet, put the cursor in the top
2278 * left corner of the edit window and get out. */
David Lawrence Ramseydbcaa3b2005-07-08 20:59:24 +00002279 if (openfile == NULL) {
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002280 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002281 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002282 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002283
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002284 openfile->current_y = openfile->current->lineno -
2285 openfile->edittop->lineno;
2286 if (openfile->current_y < editwinrows) {
David Lawrence Ramseycfffbf72005-11-16 03:14:11 +00002287 size_t xpt = xplustabs();
David Lawrence Ramsey964722a2006-05-26 03:02:50 +00002288
David Lawrence Ramseycfffbf72005-11-16 03:14:11 +00002289 wmove(edit, openfile->current_y, xpt - get_page_start(xpt));
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002290 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002291}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002292
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002293/* edit_draw() takes care of the job of actually painting a line into
2294 * the edit window. fileptr is the line to be painted, at row line of
2295 * the window. converted is the actual string to be written to the
2296 * window, with tabs and control characters replaced by strings of
2297 * regular characters. start is the column number of the first
2298 * character of this page. That is, the first character of converted
2299 * corresponds to character number actual_x(fileptr->data, start) of the
2300 * line. */
2301void edit_draw(const filestruct *fileptr, const char *converted, int
2302 line, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002303{
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002304#if !defined(NANO_TINY) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002305 size_t startpos = actual_x(fileptr->data, start);
2306 /* The position in fileptr->data of the leftmost character
2307 * that displays at least partially on the window. */
2308 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2309 /* The position in fileptr->data of the first character that is
2310 * completely off the window to the right.
2311 *
2312 * Note that endpos might be beyond the null terminator of the
2313 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002314#endif
2315
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002316 assert(openfile != NULL && fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002317 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002318
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002319 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002320 * just the text that needs it). */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002321 mvwaddstr(edit, line, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002322
Chris Allegretta7dd77682001-12-08 19:52:28 +00002323#ifdef ENABLE_COLOR
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002324 /* If color syntaxes are available and turned on, we need to display
2325 * them. */
2326 if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
2327 const colortype *tmpcolor = openfile->colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002328
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002329 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2330 int x_start;
2331 /* Starting column for mvwaddnstr. Zero-based. */
2332 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002333 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002334 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002335 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002336 /* Index in converted where we paint. */
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002337 regmatch_t startmatch;
2338 /* Match position for start_regex. */
2339 regmatch_t endmatch;
2340 /* Match position for end_regex. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002341
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002342 if (tmpcolor->bright)
2343 wattron(edit, A_BOLD);
2344 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramseyb0e04c02005-12-08 07:24:54 +00002345 /* Two notes about regexec(). A return value of zero means
2346 * that there is a match. Also, rm_eo is the first
2347 * non-matching character after the match. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002348
2349 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002350 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002351 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002352
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002353 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002354 * last match. Even though two matches may overlap, we
David Lawrence Ramsey2ef7dae2006-05-26 11:58:37 +00002355 * want to ignore them, so that we can highlight e.g. C
2356 * strings correctly. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002357 while (k < endpos) {
2358 /* Note the fifth parameter to regexec(). It says
2359 * not to match the beginning-of-line character
David Lawrence Ramsey2ef7dae2006-05-26 11:58:37 +00002360 * unless k is zero. If regexec() returns
2361 * REG_NOMATCH, there are no more matches in the
2362 * line. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002363 if (regexec(tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002364 &startmatch, (k == 0) ? 0 : REG_NOTBOL) ==
2365 REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002366 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002367 /* Translate the match to the beginning of the
2368 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002369 startmatch.rm_so += k;
2370 startmatch.rm_eo += k;
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002371
2372 /* Skip over a zero-length regex match. */
2373 if (startmatch.rm_so == startmatch.rm_eo)
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002374 startmatch.rm_eo++;
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002375 else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002376 startmatch.rm_eo > startpos) {
David Lawrence Ramseyb02a1952006-05-08 16:25:12 +00002377 x_start = (startmatch.rm_so <= startpos) ? 0 :
2378 strnlenpt(fileptr->data,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002379 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002380
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002381 index = actual_x(converted, x_start);
2382
2383 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00002384 strnlenpt(fileptr->data,
2385 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002386
2387 assert(0 <= x_start && 0 <= paintlen);
2388
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002389 mvwaddnstr(edit, line, x_start, converted +
2390 index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002391 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002392 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002393 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002394 } else {
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002395 /* This is a multi-line regex. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002396 * First, we have to see if the beginning of the line is
2397 * colored by a start on an earlier line, and an end on
2398 * this line or later.
2399 *
2400 * We find the first line before fileptr matching the
2401 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002402 * end, then go to step two. Otherwise, find the next
2403 * line after start_line matching the end. If that line
2404 * is not before fileptr, then paint the beginning of
2405 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002406 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002407 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002408 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002409 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002410 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002411
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002412 while (start_line != NULL && regexec(tmpcolor->start,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002413 start_line->data, 1, &startmatch, 0) ==
2414 REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002415 /* If there is an end on this line, there is no need
2416 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002417 if (regexec(tmpcolor->end, start_line->data, 0,
2418 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002419 goto step_two;
2420 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002421 }
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002422
2423 /* Skip over a zero-length regex match. */
2424 if (startmatch.rm_so == startmatch.rm_eo)
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002425 startmatch.rm_eo++;
David Lawrence Ramseyd76de382006-06-21 20:51:36 +00002426 else {
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002427 /* No start found, so skip to the next step. */
2428 if (start_line == NULL)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002429 goto step_two;
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002430 /* Now start_line is the first line before fileptr
2431 * containing a start match. Is there a start on
2432 * this line not followed by an end on this line? */
2433 start_col = 0;
2434 while (TRUE) {
2435 start_col += startmatch.rm_so;
2436 startmatch.rm_eo -= startmatch.rm_so;
2437 if (regexec(tmpcolor->end, start_line->data +
2438 start_col + startmatch.rm_eo, 0, NULL,
2439 (start_col + startmatch.rm_eo == 0) ?
2440 0 : REG_NOTBOL) == REG_NOMATCH)
2441 /* No end found after this start. */
2442 break;
2443 start_col++;
2444 if (regexec(tmpcolor->start, start_line->data +
2445 start_col, 1, &startmatch,
2446 REG_NOTBOL) == REG_NOMATCH)
2447 /* No later start on this line. */
2448 goto step_two;
2449 }
2450 /* Indeed, there is a start not followed on this
2451 * line by an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002452
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002453 /* We have already checked that there is no end
2454 * before fileptr and after the start. Is there an
2455 * end after the start at all? We don't paint
2456 * unterminated starts. */
2457 end_line = fileptr;
2458 while (end_line != NULL && regexec(tmpcolor->end,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002459 end_line->data, 1, &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002460 end_line = end_line->next;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002461
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002462 /* No end found, or it is too early. */
2463 if (end_line == NULL || (end_line == fileptr &&
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002464 endmatch.rm_eo <= startpos))
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002465 goto step_two;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002466
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002467 /* Now paint the start of fileptr. */
2468 if (end_line != fileptr)
2469 /* If the start of fileptr is on a different
2470 * line from the end, paintlen is -1, meaning
2471 * that everything on the line gets painted. */
2472 paintlen = -1;
2473 else
2474 /* Otherwise, paintlen is the expanded location
2475 * of the end of the match minus the expanded
2476 * location of the beginning of the page. */
2477 paintlen = actual_x(converted,
2478 strnlenpt(fileptr->data,
2479 endmatch.rm_eo) - start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002480
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002481 mvwaddnstr(edit, line, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002482
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002483 step_two:
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002484 /* Second step, we look for starts on this line. */
2485 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002486
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002487 while (start_col < endpos) {
2488 if (regexec(tmpcolor->start, fileptr->data +
2489 start_col, 1, &startmatch, (start_col ==
2490 0) ? 0 : REG_NOTBOL) == REG_NOMATCH ||
2491 start_col + startmatch.rm_so >= endpos)
2492 /* No more starts on this line. */
2493 break;
2494 /* Translate the match to be relative to the
2495 * beginning of the line. */
2496 startmatch.rm_so += start_col;
2497 startmatch.rm_eo += start_col;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002498
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002499 x_start = (startmatch.rm_so <= startpos) ? 0 :
2500 strnlenpt(fileptr->data,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002501 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002502
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002503 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002504
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002505 if (regexec(tmpcolor->end, fileptr->data +
2506 startmatch.rm_eo, 1, &endmatch,
2507 (startmatch.rm_eo == 0) ? 0 :
2508 REG_NOTBOL) == 0) {
2509 /* Translate the end match to be relative to
2510 * the beginning of the line. */
2511 endmatch.rm_so += startmatch.rm_eo;
2512 endmatch.rm_eo += startmatch.rm_eo;
2513 /* There is an end on this line. But does
2514 * it appear on this page, and is the match
2515 * more than zero characters long? */
2516 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002517 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002518 paintlen = actual_x(converted + index,
2519 strnlenpt(fileptr->data,
2520 endmatch.rm_eo) - start -
2521 x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002522
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002523 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002524
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002525 mvwaddnstr(edit, line, x_start,
2526 converted + index, paintlen);
2527 }
2528 } else {
2529 /* There is no end on this line. But we
2530 * haven't yet looked for one on later
2531 * lines. */
2532 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002533
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002534 while (end_line != NULL &&
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002535 regexec(tmpcolor->end, end_line->data,
2536 0, NULL, 0) == REG_NOMATCH)
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002537 end_line = end_line->next;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002538
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002539 if (end_line != NULL) {
2540 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002541
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002542 mvwaddnstr(edit, line, x_start,
2543 converted + index, -1);
2544 /* We painted to the end of the line, so
2545 * don't bother checking any more
2546 * starts. */
2547 break;
2548 }
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002549 }
David Lawrence Ramseya5f833d2006-05-08 15:57:04 +00002550 start_col = startmatch.rm_so + 1;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002551 }
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002552 }
2553 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002554
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002555 wattroff(edit, A_BOLD);
2556 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002557 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002558 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002559#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002560
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002561#ifndef NANO_TINY
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002562 /* If the mark is on, we need to display it. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002563 if (openfile->mark_set && (fileptr->lineno <=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002564 openfile->mark_begin->lineno || fileptr->lineno <=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002565 openfile->current->lineno) && (fileptr->lineno >=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002566 openfile->mark_begin->lineno || fileptr->lineno >=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002567 openfile->current->lineno)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002568 /* fileptr is at least partially selected. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002569 const filestruct *top;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002570 /* Either current or mark_begin, whichever is first. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002571 size_t top_x;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002572 /* current_x or mark_begin_x, corresponding to top. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002573 const filestruct *bot;
2574 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002575 int x_start;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002576 /* Starting column for mvwaddnstr(). Zero-based. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002577 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002578 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002579 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002580 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002581 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002582
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00002583 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002584
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002585 if (top->lineno < fileptr->lineno || top_x < startpos)
2586 top_x = startpos;
2587 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2588 bot_x = endpos;
2589
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002590 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002591 if (top_x < endpos && bot_x > startpos) {
2592 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002593
2594 /* x_start is the expanded location of the beginning of the
2595 * mark minus the beginning of the page. */
2596 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002597
2598 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002599 /* If the end of the mark is off the page, paintlen is
2600 * -1, meaning that everything on the line gets
2601 * painted. */
2602 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002603 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002604 /* Otherwise, paintlen is the expanded location of the
2605 * end of the mark minus the expanded location of the
2606 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002607 paintlen = strnlenpt(fileptr->data, bot_x) -
2608 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002609
2610 /* If x_start is before the beginning of the page, shift
2611 * paintlen x_start characters to compensate, and put
2612 * x_start at the beginning of the page. */
2613 if (x_start < 0) {
2614 paintlen += x_start;
2615 x_start = 0;
2616 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002617
2618 assert(x_start >= 0 && x_start <= strlen(converted));
2619
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002620 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002621
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002622 if (paintlen > 0)
2623 paintlen = actual_x(converted + index, paintlen);
2624
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002625 wattron(edit, reverse_attr);
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002626 mvwaddnstr(edit, line, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00002627 paintlen);
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00002628 wattroff(edit, reverse_attr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002629 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002630 }
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002631#endif /* !NANO_TINY */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002632}
2633
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002634/* Just update one line in the edit buffer. This is basically a wrapper
David Lawrence Ramseyb3c6b402005-11-07 06:20:02 +00002635 * for edit_draw(). The line will be displayed starting with
2636 * fileptr->data[index]. Likely arguments are current_x or zero. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002637void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002638{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002639 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002640 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002641 char *converted;
2642 /* fileptr->data converted to have tabs and control characters
2643 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002644 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002645
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002646 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002647
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002648 line = fileptr->lineno - openfile->edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002649
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002650 if (line < 0 || line >= editwinrows)
2651 return;
2652
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002653 /* First, blank out the line. */
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002654 blank_line(edit, line, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002655
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002656 /* Next, convert variables that index the line to their equivalent
2657 * positions in the expanded line. */
David Lawrence Ramseyb3c6b402005-11-07 06:20:02 +00002658 index = strnlenpt(fileptr->data, index);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002659 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002660
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002661 /* Expand the line, replacing tabs with spaces, and control
2662 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002663 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00002664
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002665 /* Paint the line. */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002666 edit_draw(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002667 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002668
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002669 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002670 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002671 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002672 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002673}
2674
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002675/* Return TRUE if we need an update after moving horizontally, and FALSE
2676 * otherwise. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002677 * placewewant are on different pages. */
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002678bool need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002679{
2680 return
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002681#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002682 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002683#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002684 get_page_start(old_pww) !=
2685 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002686}
2687
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002688/* Return TRUE if we need an update after moving vertically, and FALSE
2689 * otherwise. We need one if the mark is on or if old_pww and
2690 * placewewant are on different pages. */
2691bool need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002692{
2693 return
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002694#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002695 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002696#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002697 get_page_start(old_pww) !=
2698 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002699}
2700
2701/* Scroll the edit window in the given direction and the given number
2702 * of lines, and draw new lines on the blank lines left after the
2703 * scrolling. direction is the direction to scroll, either UP or DOWN,
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002704 * and nlines is the number of lines to scroll. We change edittop, and
David Lawrence Ramsey6969c992005-07-26 00:42:48 +00002705 * assume that current and current_x are up to date. We also assume
2706 * that scrollok(edit) is FALSE. */
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002707void edit_scroll(scroll_dir direction, ssize_t nlines)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002708{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002709 bool do_redraw = need_vertical_update(0);
David Lawrence Ramsey443a7662005-07-14 23:06:22 +00002710 const filestruct *foo;
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002711 ssize_t i;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002712
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002713 /* Don't bother scrolling less than one line. */
2714 if (nlines < 1)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002715 return;
2716
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002717 /* Part 1: nlines is the number of lines we're going to scroll the
2718 * text of the edit window. */
2719
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002720 /* Move the top line of the edit window up or down (depending on the
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002721 * value of direction) nlines lines, or as many lines as we can if
2722 * there are fewer than nlines lines available. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002723 for (i = nlines; i > 0; i--) {
2724 if (direction == UP) {
David Lawrence Ramseye99223d2005-11-10 04:27:30 +00002725 if (openfile->edittop == openfile->fileage)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002726 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002727 openfile->edittop = openfile->edittop->prev;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002728 } else {
David Lawrence Ramseye99223d2005-11-10 04:27:30 +00002729 if (openfile->edittop == openfile->filebot)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002730 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002731 openfile->edittop = openfile->edittop->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002732 }
2733 }
2734
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00002735 /* Limit nlines to the number of lines we could scroll. */
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00002736 nlines -= i;
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00002737
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00002738 /* Don't bother scrolling zero lines or more than the number of
2739 * lines in the edit window minus one; in both cases, get out, and
2740 * in the latter case, call edit_refresh() beforehand. */
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00002741 if (nlines == 0)
2742 return;
2743
2744 if (nlines >= editwinrows) {
2745 edit_refresh();
2746 return;
2747 }
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002748
2749 /* Scroll the text of the edit window up or down nlines lines,
2750 * depending on the value of direction. */
David Lawrence Ramsey47bb8882005-07-22 22:56:03 +00002751 scrollok(edit, TRUE);
2752 wscrl(edit, (direction == UP) ? -nlines : nlines);
2753 scrollok(edit, FALSE);
2754
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002755 /* Part 2: nlines is the number of lines in the scrolled region of
2756 * the edit window that we need to draw. */
2757
David Lawrence Ramsey68346502005-08-16 03:03:15 +00002758 /* If the top or bottom line of the file is now visible in the edit
2759 * window, we need to draw the entire edit window. */
2760 if ((direction == UP && openfile->edittop == openfile->fileage) ||
2761 (direction == DOWN && openfile->edittop->lineno + editwinrows -
2762 1 >= openfile->filebot->lineno))
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00002763 nlines = editwinrows;
David Lawrence Ramseya7f488b2005-07-17 02:19:47 +00002764
David Lawrence Ramseya6eb8482006-01-10 07:51:49 +00002765 /* If the scrolled region contains only one line, and the line
2766 * before it is visible in the edit window, we need to draw it too.
2767 * If the scrolled region contains more than one line, and the lines
2768 * before and after the scrolled region are visible in the edit
2769 * window, we need to draw them too. */
2770 nlines += (nlines == 1) ? 1 : 2;
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00002771
David Lawrence Ramseyde0c5eb2005-07-17 22:51:44 +00002772 if (nlines > editwinrows)
2773 nlines = editwinrows;
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002774
2775 /* If we scrolled up, we're on the line before the scrolled
2776 * region. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002777 foo = openfile->edittop;
David Lawrence Ramsey14588912005-07-14 20:37:01 +00002778
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002779 /* If we scrolled down, move down to the line before the scrolled
2780 * region. */
David Lawrence Ramsey14588912005-07-14 20:37:01 +00002781 if (direction == DOWN) {
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002782 for (i = editwinrows - nlines; i > 0 && foo != NULL; i--)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002783 foo = foo->next;
2784 }
2785
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002786 /* Draw new lines on any blank lines before or inside the scrolled
2787 * region. If we scrolled down and we're on the top line, or if we
2788 * scrolled up and we're on the bottom line, the line won't be
2789 * blank, so we don't need to draw it unless the mark is on or we're
2790 * not on the first page. */
2791 for (i = nlines; i > 0 && foo != NULL; i--) {
2792 if ((i == nlines && direction == DOWN) || (i == 1 &&
2793 direction == UP)) {
2794 if (do_redraw)
2795 update_line(foo, (foo == openfile->current) ?
2796 openfile->current_x : 0);
2797 } else
2798 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002799 openfile->current_x : 0);
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00002800 foo = foo->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002801 }
2802}
2803
2804/* Update any lines between old_current and current that need to be
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00002805 * updated. Use this if we've moved without changing any text. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002806void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002807{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002808 bool do_redraw = need_vertical_update(0) ||
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00002809 need_vertical_update(old_pww);
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00002810 const filestruct *foo = NULL;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002811
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002812 /* If either old_current or current is offscreen, scroll the edit
2813 * window until it's onscreen and get out. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002814 if (old_current->lineno < openfile->edittop->lineno ||
2815 old_current->lineno >= openfile->edittop->lineno +
2816 editwinrows || openfile->current->lineno <
2817 openfile->edittop->lineno || openfile->current->lineno >=
2818 openfile->edittop->lineno + editwinrows) {
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002819 filestruct *old_edittop = openfile->edittop;
2820 ssize_t nlines;
2821
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00002822#ifndef NANO_TINY
2823 /* If the mark is on, update all the lines between old_current
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00002824 * and either the old first line or old last line (depending on
2825 * whether we've scrolled up or down) of the edit window. */
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00002826 if (openfile->mark_set) {
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00002827 ssize_t old_lineno;
2828
2829 if (old_edittop->lineno < openfile->edittop->lineno)
2830 old_lineno = old_edittop->lineno;
2831 else
2832 old_lineno = (old_edittop->lineno + editwinrows <=
2833 openfile->filebot->lineno) ?
2834 old_edittop->lineno + editwinrows :
2835 openfile->filebot->lineno;
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00002836
2837 foo = old_current;
2838
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00002839 while (foo->lineno != old_lineno) {
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00002840 update_line(foo, 0);
2841
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00002842 foo = (foo->lineno > old_lineno) ? foo->prev :
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00002843 foo->next;
2844 }
2845 }
2846#endif /* !NANO_TINY */
2847
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002848 /* Put edittop in range of current, get the difference in lines
2849 * between the original edittop and the current edittop, and
2850 * then restore the original edittop. */
2851 edit_update(
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002852#ifndef NANO_TINY
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002853 ISSET(SMOOTH_SCROLL) ? NONE :
2854#endif
2855 CENTER);
2856
2857 nlines = openfile->edittop->lineno - old_edittop->lineno;
2858
2859 openfile->edittop = old_edittop;
2860
David Lawrence Ramseyb0063672006-07-06 18:29:37 +00002861 /* Update old_current if we're not on the same page as
2862 * before. */
David Lawrence Ramseya6eb8482006-01-10 07:51:49 +00002863 if (do_redraw)
2864 update_line(old_current, 0);
2865
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00002866 /* Scroll the edit window up or down until edittop is in range
2867 * of current. */
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002868 if (nlines < 0)
2869 edit_scroll(UP, -nlines);
2870 else
2871 edit_scroll(DOWN, nlines);
2872
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00002873#ifndef NANO_TINY
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00002874 /* If the mark is on, update all the lines between the old first
2875 * line or old last line of the edit window (depending on
2876 * whether we've scrolled up or down) and current. */
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00002877 if (openfile->mark_set) {
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00002878 while (foo->lineno != openfile->current->lineno) {
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00002879 update_line(foo, 0);
2880
David Lawrence Ramsey3c780e12006-05-26 03:46:03 +00002881 foo = (foo->lineno > openfile->current->lineno) ?
David Lawrence Ramseyd5228b32006-05-26 03:04:24 +00002882 foo->prev : foo->next;
2883 }
2884 }
2885#endif /* !NANO_TINY */
2886
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002887 return;
2888 }
2889
David Lawrence Ramseyb0063672006-07-06 18:29:37 +00002890 /* Update old_current and current if we're not on the same page as
2891 * before. If the mark is on, update all the lines between
2892 * old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002893 foo = old_current;
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00002894
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002895 while (foo != openfile->current) {
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002896 if (do_redraw)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002897 update_line(foo, 0);
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00002898
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002899#ifndef NANO_TINY
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002900 if (!openfile->mark_set)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002901#endif
2902 break;
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00002903
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002904#ifndef NANO_TINY
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00002905 foo = (foo->lineno > openfile->current->lineno) ? foo->prev :
2906 foo->next;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002907#endif
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002908 }
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00002909
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002910 if (do_redraw)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002911 update_line(openfile->current, openfile->current_x);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002912}
2913
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00002914/* Refresh the screen without changing the position of lines. Use this
2915 * if we've moved and changed text. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002916void edit_refresh(void)
2917{
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002918 const filestruct *foo;
2919 int nlines;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002920
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002921 if (openfile->current->lineno < openfile->edittop->lineno ||
2922 openfile->current->lineno >= openfile->edittop->lineno +
2923 editwinrows)
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002924 /* Put the top line of the edit window in range of the current
2925 * line. */
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002926 edit_update(
David Lawrence Ramseyebe34252005-11-15 03:17:35 +00002927#ifndef NANO_TINY
David Lawrence Ramseyb2b69762005-06-16 02:13:10 +00002928 ISSET(SMOOTH_SCROLL) ? NONE :
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002929#endif
2930 CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002931
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002932 foo = openfile->edittop;
2933
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002934#ifdef DEBUG
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002935 fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", (long)openfile->edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002936#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002937
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002938 for (nlines = 0; nlines < editwinrows && foo != NULL; nlines++) {
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002939 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002940 openfile->current_x : 0);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002941 foo = foo->next;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002942 }
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002943
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002944 for (; nlines < editwinrows; nlines++)
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002945 blank_line(edit, nlines, 0, COLS);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002946
2947 reset_cursor();
David Lawrence Ramsey51b7b0e2006-07-05 06:38:47 +00002948
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002949 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002950}
2951
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002952/* Move edittop to put it in range of current, keeping current in the
2953 * same place. location determines how we move it: if it's CENTER, we
2954 * center current, and if it's NONE, we put current current_y lines
2955 * below edittop. */
David Lawrence Ramseybf0e47d2005-08-01 18:27:10 +00002956void edit_update(update_type location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002957{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002958 filestruct *foo = openfile->current;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002959 int goal;
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00002960
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002961 /* If location is CENTER, we move edittop up (editwinrows / 2)
2962 * lines. This puts current at the center of the screen. If
2963 * location is NONE, we move edittop up current_y lines if current_y
2964 * is in range of the screen, 0 lines if current_y is less than 0,
2965 * or (editwinrows - 1) lines if current_y is greater than
2966 * (editwinrows - 1). This puts current at the same place on the
2967 * screen as before, or at the top or bottom of the screen if
2968 * edittop is beyond either. */
2969 if (location == CENTER)
2970 goal = editwinrows / 2;
2971 else {
2972 goal = openfile->current_y;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002973
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002974 /* Limit goal to (editwinrows - 1) lines maximum. */
2975 if (goal > editwinrows - 1)
2976 goal = editwinrows - 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002977 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002978
David Lawrence Ramseyb885c9c2005-11-10 05:20:25 +00002979 for (; goal > 0 && foo->prev != NULL; goal--)
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002980 foo = foo->prev;
2981
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002982 openfile->edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002983}
2984
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002985/* Unconditionally redraw the entire screen. */
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00002986void total_redraw(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002987{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002988#ifdef USE_SLANG
David Lawrence Ramseyb5e66d02006-06-09 16:57:41 +00002989 /* Slang curses emulation brain damage, part 4: Slang doesn't define
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002990 * curscr. */
2991 SLsmg_touch_screen();
2992 SLsmg_refresh();
2993#else
2994 wrefresh(curscr);
2995#endif
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002996}
2997
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00002998/* Unconditionally redraw the entire screen, and then refresh it using
2999 * the current file. */
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003000void total_refresh(void)
3001{
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003002 total_redraw();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003003 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003004 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003005 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003006}
3007
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003008/* Display the main shortcut list on the last two rows of the bottom
3009 * portion of the window. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003010void display_main_list(void)
3011{
3012 bottombars(main_list);
3013}
3014
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003015/* If constant is TRUE, we display the current cursor position only if
3016 * disable_cursorpos is FALSE. Otherwise, we display it
3017 * unconditionally and set disable_cursorpos to FALSE. If constant is
3018 * TRUE and disable_cursorpos is TRUE, we also set disable_cursorpos to
3019 * FALSE, so that we leave the current statusbar alone this time, and
3020 * display the current cursor position next time. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003021void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003022{
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003023 filestruct *f;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003024 char c;
David Lawrence Ramsey5745c0a2005-07-31 20:20:37 +00003025 size_t i, cur_xpt = xplustabs() + 1;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003026 size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003027 int linepct, colpct, charpct;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003028
David Lawrence Ramsey4ab80152005-07-31 18:51:51 +00003029 assert(openfile->fileage != NULL && openfile->current != NULL);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003030
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003031 f = openfile->current->next;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003032 c = openfile->current->data[openfile->current_x];
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003033
3034 openfile->current->next = NULL;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003035 openfile->current->data[openfile->current_x] = '\0';
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003036
3037 i = get_totsize(openfile->fileage, openfile->current);
3038
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003039 openfile->current->data[openfile->current_x] = c;
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003040 openfile->current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003041
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003042 if (constant && disable_cursorpos) {
3043 disable_cursorpos = FALSE;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003044 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003045 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003046
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003047 /* Display the current cursor position on the statusbar, and set
3048 * disable_cursorpos to FALSE. */
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003049 linepct = 100 * openfile->current->lineno /
3050 openfile->filebot->lineno;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003051 colpct = 100 * cur_xpt / cur_lenpt;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003052 charpct = (openfile->totsize == 0) ? 0 : 100 * i /
3053 openfile->totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003054
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003055 statusbar(
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003056 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003057 (long)openfile->current->lineno,
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003058 (long)openfile->filebot->lineno, linepct,
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003059 (unsigned long)cur_xpt, (unsigned long)cur_lenpt, colpct,
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003060 (unsigned long)i, (unsigned long)openfile->totsize, charpct);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003061
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003062 disable_cursorpos = FALSE;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003063}
3064
David Lawrence Ramsey6d6a36c2005-12-08 07:09:08 +00003065/* Unconditionally display the current cursor position. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003066void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003067{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003068 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003069}
3070
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003071/* Highlight the current word being replaced or spell checked. We
3072 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003073void do_replace_highlight(bool highlight, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003074{
David Lawrence Ramsey6168cb72005-06-30 03:53:28 +00003075 size_t y = xplustabs(), word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003076
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003077 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003078 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003079 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003080
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003081 assert(y > 0);
3082
3083 if (word_len > y)
3084 y--;
3085
Chris Allegrettafb62f732000-12-05 11:36:41 +00003086 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003087
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003088 if (highlight)
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00003089 wattron(edit, reverse_attr);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003090
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003091#ifdef HAVE_REGEX_H
David Lawrence Ramsey5aaa1d72006-06-21 01:30:00 +00003092 /* This is so we can show zero-length regex matches. */
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003093 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00003094 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003095 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003096#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003097 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003098
3099 if (word_len > y)
3100 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003101
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003102 if (highlight)
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00003103 wattroff(edit, reverse_attr);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003104}
3105
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003106#ifdef NANO_EXTRA
David Lawrence Ramsey315eb322005-11-28 19:35:29 +00003107#define CREDIT_LEN 55
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003108#define XLCREDIT_LEN 8
3109
David Lawrence Ramsey8ad58bc2005-08-16 03:02:46 +00003110/* Easter egg: Display credits. Assume nodelay(edit) and scrollok(edit)
3111 * are FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003112void do_credits(void)
3113{
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003114 bool old_more_space = ISSET(MORE_SPACE);
3115 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003116 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003117 const char *credits[CREDIT_LEN] = {
3118 NULL, /* "The nano text editor" */
3119 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003120 VERSION,
3121 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003122 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003123 "Chris Allegretta",
3124 "Jordi Mallach",
3125 "Adam Rogoyski",
3126 "Rob Siemborski",
3127 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003128 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003129 "David Benbennick",
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003130 "Mike Frysinger",
Chris Allegretta598106e2002-01-19 01:59:37 +00003131 "Ken Tyler",
3132 "Sven Guckes",
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003133 NULL, /* credits[15], handled below. */
Chris Allegretta598106e2002-01-19 01:59:37 +00003134 "Pauli Virtanen",
3135 "Daniele Medri",
3136 "Clement Laforet",
3137 "Tedi Heriyanto",
3138 "Bill Soudan",
3139 "Christian Weisgerber",
3140 "Erik Andersen",
3141 "Big Gaute",
3142 "Joshua Jensen",
3143 "Ryan Krebs",
3144 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003145 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003146 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003147 "Plattsburgh State University",
3148 "Benet Laboratories",
3149 "Amy Allegretta",
3150 "Linda Young",
3151 "Jeremy Robichaud",
3152 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003153 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003154 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003155 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003156 "Thomas Dickey",
3157 "Pavel Curtis",
3158 "Zeyd Ben-Halim",
3159 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003160 NULL, /* "and anyone else we forgot..." */
3161 NULL, /* "Thank you for using nano!" */
3162 "",
3163 "",
3164 "",
3165 "",
David Lawrence Ramsey315eb322005-11-28 19:35:29 +00003166 "(c) 1999-2004 Chris Allegretta",
David Lawrence Ramsey4f4a0b92006-05-13 16:32:24 +00003167 "(c) 2005-2006 David Lawrence Ramsey",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003168 "",
3169 "",
3170 "",
3171 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003172 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003173 };
3174
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003175 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003176 N_("The nano text editor"),
3177 N_("version"),
3178 N_("Brought to you by:"),
3179 N_("Special thanks to:"),
3180 N_("The Free Software Foundation"),
3181 N_("For ncurses:"),
3182 N_("and anyone else we forgot..."),
3183 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003184 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003185
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003186 /* credits[15]: Make sure this name is displayed properly, since we
David Lawrence Ramsey62d616b2005-07-06 19:20:32 +00003187 * can't dynamically assign it above, using Unicode 00F6 (Latin
3188 * Small Letter O with Diaresis) if applicable. */
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003189 credits[15] =
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00003190#ifdef ENABLE_UTF8
David Lawrence Ramsey4d72de72006-04-12 15:27:40 +00003191 using_utf8() ? "Florian K\xC3\xB6nig" :
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003192#endif
3193 "Florian K\xF6nig";
3194
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003195 if (!old_more_space || !old_no_help) {
3196 SET(MORE_SPACE);
3197 SET(NO_HELP);
3198 window_init();
3199 }
3200
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003201 curs_set(0);
3202 nodelay(edit, TRUE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003203
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003204 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003205 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003206 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003207 blank_statusbar();
3208 blank_bottombars();
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003209
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003210 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003211 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003212 wrefresh(bottomwin);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003213 napms(700);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003214
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003215 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003216 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003217 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003218
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003219 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003220 const char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003221 size_t start_x;
3222
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003223 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003224 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003225
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003226 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003227 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003228 } else
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003229 what = credits[crpos];
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003230
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003231 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003232 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
3233 start_x, what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003234 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003235
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003236 wrefresh(edit);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003237
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003238 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003239 break;
3240 napms(700);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003241
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003242 scrollok(edit, TRUE);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003243 wscrl(edit, 1);
3244 scrollok(edit, FALSE);
3245 wrefresh(edit);
3246
3247 if ((kbinput = wgetch(edit)) != ERR)
3248 break;
3249 napms(700);
3250
3251 scrollok(edit, TRUE);
3252 wscrl(edit, 1);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003253 scrollok(edit, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003254 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003255 }
3256
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003257 if (kbinput != ERR)
3258 ungetch(kbinput);
3259
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003260 if (!old_more_space || !old_no_help) {
3261 UNSET(MORE_SPACE);
3262 UNSET(NO_HELP);
3263 window_init();
3264 }
3265
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003266 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003267 nodelay(edit, FALSE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003268
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003269 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003270}
David Lawrence Ramsey172aa932006-04-18 15:58:50 +00003271#endif /* NANO_EXTRA */