blob: 8151be52c5ac873f80d51d8d12289a6da7a66419 [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 Ramseyc13b7f02005-01-01 07:28:15 +00005 * Copyright (C) 1999-2005 Chris Allegretta *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00006 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * any later version. *
10 * *
David Lawrence Ramsey6e925cf2005-05-15 19:57:17 +000011 * This program is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * General Public License for more details. *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000015 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
David Lawrence Ramsey6e925cf2005-05-15 19:57:17 +000018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
19 * 02110-1301, USA. *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000020 * *
21 **************************************************************************/
22
Jordi Mallach55381aa2004-11-17 23:17:05 +000023#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000026
David Lawrence Ramsey143b8c72005-11-01 18:35:47 +000027#include <stdio.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000028#include <stdarg.h>
29#include <string.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000030#include <unistd.h>
David Lawrence Ramsey6f5de422005-10-06 05:28:37 +000031#include <errno.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000032#include <ctype.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000033#include "proto.h"
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000034
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +000035static int *key_buffer = NULL;
David Lawrence Ramsey74835712004-12-04 17:41:52 +000036 /* The default keystroke buffer,
37 * containing all the keystrokes we have
38 * at a given point. */
39static size_t key_buffer_len = 0;
40 /* The length of the default keystroke
41 * buffer. */
David Lawrence Ramseyfe7d53e2005-06-25 20:56:36 +000042static int statusblank = 0;
43 /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000044 * we call statusbar(), before we
45 * actually blank the statusbar. */
David Lawrence Ramseyea014742005-06-17 18:27:00 +000046static bool disable_cursorpos = FALSE;
47 /* Should we temporarily disable
48 * constant cursor position display? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000049
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000050/* Control character compatibility:
51 *
52 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
53 * VT100, and VT220.
54 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
55 * VT220, and VT320.
56 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
57 * VT220, and VT320.
58 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
59 * VT220, and VT320.
60 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
61 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000062 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000063 * ANSI, VT100, and VT220, and which is Backspace under VT320.
64 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000065 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000066 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
67 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000068 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000069 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000070 * on which the VT320 sequences are translated by the keypad to KEY_DC
71 * and [nothing]. We work around this conflict via the REBIND_DELETE
72 * flag: if it's not set, we assume VT320 compatibility, and if it is,
73 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
74 * Hemel for helping work this conflict out.
75 *
76 * Escape sequence compatibility:
77 *
78 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000079 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000080 * console), xterm, rxvt, and Eterm. Among these, there are several
81 * conflicts and omissions, outlined as follows:
82 *
83 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
84 * (Ctrl-I is also Tab on ANSI, which we already support.)
85 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
86 * NumLock off on Linux console; the latter is omitted. (The editing
87 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000088 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000089 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
90 * latter is omitted. (Mouse input will only work properly if the
91 * extended keypad value KEY_MOUSE is generated on mouse events
92 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000093 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000094 * omitted. (The editing keypad is more important to have working
95 * than the function keys, because the functions of the former are not
96 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000097 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000098 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000099 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000100 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000101 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
102 * omitted. (The arrow keys, with or without modifiers, are more
103 * important to have working than the function keys, because the
104 * functions of the former are not arbitrary and the functions of the
105 * latter are.)
106 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
107 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000108 *
109 * Note that Center (5) on the numeric keypad with NumLock off can also
110 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000111
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000112#ifndef NANO_SMALL
113/* Reset all the input routines that rely on character sequences. */
114void reset_kbinput(void)
115{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000116 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000117 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey6a836472005-08-01 19:12:05 +0000118 get_unicode_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000119}
120#endif
121
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000122/* Read in a sequence of keystrokes from win and save them in the
123 * default keystroke buffer. This should only be called when the
124 * default keystroke buffer is empty. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000125void get_key_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000126{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000127 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000128
129 /* If the keystroke buffer isn't empty, get out. */
130 if (key_buffer != NULL)
131 return;
132
133 /* Read in the first character using blocking input. */
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000134#ifndef NANO_SMALL
135 allow_pending_sigwinch(TRUE);
136#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000137
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +0000138 /* Just before reading in the first character, display any pending
139 * screen updates. */
140 doupdate();
141
David Lawrence Ramsey6f5de422005-10-06 05:28:37 +0000142 while ((input = wgetch(win)) == ERR) {
143 /* If errno is EIO, it means that the input source that we were
144 * using is gone, so die gracefully. */
145 if (errno == EIO)
146 handle_hupterm(0);
147 }
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000148
David Lawrence Ramseyc275dc52005-03-08 17:45:36 +0000149
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000150#ifndef NANO_SMALL
151 allow_pending_sigwinch(FALSE);
152#endif
153
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000154 /* Increment the length of the keystroke buffer, save the value of
155 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000156 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000157 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000158 key_buffer = (int *)nmalloc(sizeof(int));
159 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000160
161 /* Read in the remaining characters using non-blocking input. */
162 nodelay(win, TRUE);
163
164 while (TRUE) {
165#ifndef NANO_SMALL
166 allow_pending_sigwinch(TRUE);
167#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000168
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000169 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000170
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000171 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000172 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000173 break;
174
175 /* Otherwise, increment the length of the keystroke buffer, save
176 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000177 * if the keystroke is an extended keypad value or FALSE if it
178 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000179 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000180 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
181 sizeof(int));
182 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000183
184#ifndef NANO_SMALL
185 allow_pending_sigwinch(FALSE);
186#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000187 }
188
189 /* Switch back to non-blocking input. */
190 nodelay(win, FALSE);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000191
192#ifdef DEBUG
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000193 fprintf(stderr, "get_key_buffer(): key_buffer_len = %lu\n", (unsigned long)key_buffer_len);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000194#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000195}
196
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000197/* Return the length of the default keystroke buffer. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000198size_t get_key_buffer_len(void)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000199{
200 return key_buffer_len;
201}
202
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000203/* Add the contents of the keystroke buffer input to the default
204 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000205void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000206{
207#ifndef NANO_SMALL
208 allow_pending_sigwinch(TRUE);
209 allow_pending_sigwinch(FALSE);
210#endif
211
212 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000213 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000214 return;
215
216 /* If adding input would put the default keystroke buffer beyond
217 * maximum capacity, only add enough of input to put it at maximum
218 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000219 if (key_buffer_len + input_len < key_buffer_len)
220 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000221
222 /* Add the length of input to the length of the default keystroke
223 * buffer, and reallocate the default keystroke buffer so that it
224 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000225 key_buffer_len += input_len;
226 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
227 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000228
229 /* If the default keystroke buffer wasn't empty before, move its
230 * beginning forward far enough so that we can add input to its
231 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000232 if (key_buffer_len > input_len)
233 memmove(key_buffer + input_len, key_buffer,
234 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000235
236 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000237 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000238}
239
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000240/* Put back the character stored in kbinput, putting it in byte range
241 * beforehand. If meta_key is TRUE, put back the Escape character after
242 * putting back kbinput. If func_key is TRUE, put back the function key
243 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000244void unget_kbinput(int kbinput, bool meta_key, bool func_key)
245{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000246 if (!func_key)
247 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000248
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000249 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000250
251 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000252 kbinput = NANO_CONTROL_3;
253 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000254 }
255}
256
257/* Try to read input_len characters from the default keystroke buffer.
258 * If the default keystroke buffer is empty and win isn't NULL, try to
259 * read in more characters from win and add them to the default
260 * keystroke buffer before doing anything else. If the default
261 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000262int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000263{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000264 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000265
266#ifndef NANO_SMALL
267 allow_pending_sigwinch(TRUE);
268 allow_pending_sigwinch(FALSE);
269#endif
270
271 if (key_buffer_len == 0) {
272 if (win != NULL)
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000273 get_key_buffer(win);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000274
275 if (key_buffer_len == 0)
276 return NULL;
277 }
278
279 /* If input_len is greater than the length of the default keystroke
280 * buffer, only read the number of characters in the default
281 * keystroke buffer. */
282 if (input_len > key_buffer_len)
283 input_len = key_buffer_len;
284
285 /* Subtract input_len from the length of the default keystroke
286 * buffer, and allocate the keystroke buffer input so that it
287 * has enough room for input_len keystrokes. */
288 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000289 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000290
291 /* Copy input_len characters from the beginning of the default
292 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000293 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000294
295 /* If the default keystroke buffer is empty, mark it as such. */
296 if (key_buffer_len == 0) {
297 free(key_buffer);
298 key_buffer = NULL;
299 /* If the default keystroke buffer isn't empty, move its
David Lawrence Ramsey1c367b62005-09-04 03:29:47 +0000300 * beginning forward far enough so that the keystrokes in input are
301 * no longer at its beginning. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000302 } else {
303 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000304 sizeof(int));
305 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
306 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000307 }
308
309 return input;
310}
311
312/* Read in a single character. If it's ignored, swallow it and go on.
313 * Otherwise, try to translate it from ASCII, meta key sequences, escape
314 * sequences, and/or extended keypad values. Set meta_key to TRUE when
315 * we get a meta key sequence, and set func_key to TRUE when we get an
316 * extended keypad value. Supported extended keypad values consist of
317 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
318 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
319 * the function keypad (F1-F16), and the numeric keypad with NumLock
320 * off. Assume nodelay(win) is FALSE. */
321int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
322{
323 int kbinput;
324
325 /* Read in a character and interpret it. Continue doing this until
326 * we get a recognized value or sequence. */
327 while ((kbinput = parse_kbinput(win, meta_key, func_key
328#ifndef NANO_SMALL
329 , FALSE
330#endif
331 )) == ERR);
332
333 return kbinput;
334}
335
336/* Translate ASCII characters, extended keypad values, and escape
337 * sequences into their corresponding key values. Set meta_key to TRUE
338 * when we get a meta key sequence, and set func_key to TRUE when we get
339 * a function key. Assume nodelay(win) is FALSE. */
340int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000341#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000342 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000343#endif
344 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000345
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000346{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000347 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000348 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000349
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000350#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000351 if (reset) {
352 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000353 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000354 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000355 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000356#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000357
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000358 *meta_key = FALSE;
359 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000360
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000361 /* Read in a character. */
362 while ((kbinput = get_input(win, 1)) == NULL);
363
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000364 switch (*kbinput) {
365 case ERR:
366 break;
367 case NANO_CONTROL_3:
368 /* Increment the escape counter. */
369 escapes++;
370 switch (escapes) {
371 case 1:
372 /* One escape: wait for more input. */
373 case 2:
374 /* Two escapes: wait for more input. */
375 break;
376 default:
377 /* More than two escapes: reset the escape counter
378 * and wait for more input. */
379 escapes = 0;
380 }
381 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000382#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000383 /* Since we don't change the default SIGWINCH handler when
384 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
385 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
386 case KEY_RESIZE:
387 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000388#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000389#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000390 case KEY_SHIFT_L:
391 case KEY_SHIFT_R:
392 case KEY_CONTROL_L:
393 case KEY_CONTROL_R:
394 case KEY_ALT_L:
395 case KEY_ALT_R:
396 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000397#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000398 default:
399 switch (escapes) {
400 case 0:
401 switch (*kbinput) {
402 case NANO_CONTROL_8:
403 retval = ISSET(REBIND_DELETE) ?
404 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
405 break;
406 case KEY_DOWN:
407 retval = NANO_NEXTLINE_KEY;
408 break;
409 case KEY_UP:
410 retval = NANO_PREVLINE_KEY;
411 break;
412 case KEY_LEFT:
413 retval = NANO_BACK_KEY;
414 break;
415 case KEY_RIGHT:
416 retval = NANO_FORWARD_KEY;
417 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000418#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000419 /* HP-UX 10 and 11 don't support KEY_HOME. */
420 case KEY_HOME:
421 retval = NANO_HOME_KEY;
422 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000423#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000424 case KEY_BACKSPACE:
425 retval = NANO_BACKSPACE_KEY;
426 break;
427 case KEY_DC:
428 retval = ISSET(REBIND_DELETE) ?
429 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
430 break;
431 case KEY_IC:
432 retval = NANO_INSERTFILE_KEY;
433 break;
434 case KEY_NPAGE:
435 retval = NANO_NEXTPAGE_KEY;
436 break;
437 case KEY_PPAGE:
438 retval = NANO_PREVPAGE_KEY;
439 break;
440 case KEY_ENTER:
441 retval = NANO_ENTER_KEY;
442 break;
443 case KEY_A1: /* Home (7) on numeric keypad
444 * with NumLock off. */
445 retval = NANO_HOME_KEY;
446 break;
447 case KEY_A3: /* PageUp (9) on numeric keypad
448 * with NumLock off. */
449 retval = NANO_PREVPAGE_KEY;
450 break;
451 case KEY_B2: /* Center (5) on numeric keypad
452 * with NumLock off. */
453 break;
454 case KEY_C1: /* End (1) on numeric keypad
455 * with NumLock off. */
456 retval = NANO_END_KEY;
457 break;
458 case KEY_C3: /* PageDown (4) on numeric
459 * keypad with NumLock off. */
460 retval = NANO_NEXTPAGE_KEY;
461 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000462#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000463 /* Slang doesn't support KEY_BEG. */
464 case KEY_BEG: /* Center (5) on numeric keypad
465 * with NumLock off. */
466 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000467#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000468#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000469 /* HP-UX 10 and 11 don't support KEY_END. */
470 case KEY_END:
471 retval = NANO_END_KEY;
472 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000473#endif
474#ifdef KEY_SUSPEND
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000475 /* Slang doesn't support KEY_SUSPEND. */
476 case KEY_SUSPEND:
477 retval = NANO_SUSPEND_KEY;
478 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000479#endif
480#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000481 /* Slang doesn't support KEY_SLEFT. */
482 case KEY_SLEFT:
483 retval = NANO_BACK_KEY;
484 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000485#endif
486#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000487 /* Slang doesn't support KEY_SRIGHT. */
488 case KEY_SRIGHT:
489 retval = NANO_FORWARD_KEY;
490 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000491#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000492 default:
493 retval = *kbinput;
494 break;
495 }
496 break;
497 case 1:
498 /* One escape followed by a non-escape: escape
499 * sequence mode. Reset the escape counter. If
500 * there aren't any other keys waiting, we have a
501 * meta key sequence, so set meta_key to TRUE and
502 * save the lowercase version of the non-escape
503 * character as the result. If there are other keys
504 * waiting, we have a true escape sequence, so
505 * interpret it. */
506 escapes = 0;
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000507 if (get_key_buffer_len() == 0) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000508 *meta_key = TRUE;
509 retval = tolower(*kbinput);
510 } else {
511 int *seq;
512 size_t seq_len;
513 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000514
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000515 /* Put back the non-escape character, get the
516 * complete escape sequence, translate the
517 * sequence into its corresponding key value,
518 * and save that as the result. */
519 unget_input(kbinput, 1);
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000520 seq_len = get_key_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000521 seq = get_input(NULL, seq_len);
522 retval = get_escape_seq_kbinput(seq, seq_len,
523 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000524
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000525 /* If the escape sequence is unrecognized and
526 * not ignored, put back all of its characters
527 * except for the initial escape. */
528 if (retval == ERR && !ignore_seq)
529 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000530
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000531 free(seq);
532 }
533 break;
534 case 2:
535 /* Two escapes followed by one or more decimal
David Lawrence Ramsey38f70a52005-07-19 18:46:02 +0000536 * digits: byte sequence mode. If the byte
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000537 * sequence's range is limited to 2XX (the first
538 * digit is in the '0' to '2' range and it's the
539 * first digit, or it's in the '0' to '9' range and
540 * it's not the first digit), increment the byte
541 * sequence counter and interpret the digit. If the
542 * byte sequence's range is not limited to 2XX, fall
543 * through. */
544 if (('0' <= *kbinput && *kbinput <= '6' &&
545 byte_digits == 0) || ('0' <= *kbinput &&
546 *kbinput <= '9' && byte_digits > 0)) {
547 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000548
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000549 byte_digits++;
550 byte = get_byte_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000551#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000552 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000553#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000554 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000555
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000556 if (byte != ERR) {
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000557 char *byte_mb;
558 int byte_mb_len, *seq, i;
559
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000560 /* If we've read in a complete byte
561 * sequence, reset the byte sequence counter
562 * and the escape counter, and put back the
563 * corresponding byte value. */
564 byte_digits = 0;
565 escapes = 0;
566
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000567 /* Put back the multibyte equivalent of the
568 * byte value. */
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +0000569 byte_mb = make_mbchar((long)byte,
570 &byte_mb_len);
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000571
572 seq = (int *)nmalloc(byte_mb_len *
573 sizeof(int));
574
575 for (i = 0; i < byte_mb_len; i++)
576 seq[i] = (unsigned char)byte_mb[i];
577
578 unget_input(seq, byte_mb_len);
579
580 free(byte_mb);
581 free(seq);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000582 }
583 } else {
584 /* Reset the escape counter. */
585 escapes = 0;
586 if (byte_digits == 0)
587 /* Two escapes followed by a non-decimal
588 * digit or a decimal digit that would
589 * create a byte sequence greater than 2XX,
590 * and we're not in the middle of a byte
591 * sequence: control character sequence
592 * mode. Interpret the control sequence and
593 * save the corresponding control character
594 * as the result. */
595 retval = get_control_kbinput(*kbinput);
596 else {
597 /* If we're in the middle of a byte
598 * sequence, reset the byte sequence counter
599 * and save the character we got as the
600 * result. */
601 byte_digits = 0;
602 retval = *kbinput;
603 }
604 }
605 break;
606 }
607 }
608
609 /* If we have a result and it's an extended keypad value (i.e, a
610 * value outside of byte range), set func_key to TRUE. */
611 if (retval != ERR)
612 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000613
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000614#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000615 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 +0000616#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000617
618 /* Return the result. */
619 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000620}
621
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000622/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000623 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000624 * are generated when the keypad doesn't support the needed keys. If
625 * the escape sequence is recognized but we want to ignore it, return
626 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
627 * set ignore_seq to FALSE. Assume that Escape has already been read
628 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000629int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000630 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000631{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000632 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000633
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000634 *ignore_seq = FALSE;
635
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000636 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000637 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000638 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000639 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000640 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000641 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000642 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000643 case 'P': /* Esc O 2 P == F13 on
644 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000645 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000646 break;
647 case 'Q': /* Esc O 2 Q == F14 on
648 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000649 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000650 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000651 case 'R': /* Esc O 2 R == F15 on
652 * xterm. */
653 retval = KEY_F(15);
654 break;
655 case 'S': /* Esc O 2 S == F16 on
656 * xterm. */
657 retval = KEY_F(16);
658 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000659 }
660 }
661 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000662 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
663 case 'B': /* Esc O B == Down on
664 * VT100/VT320/xterm. */
665 case 'C': /* Esc O C == Right on
666 * VT100/VT320/xterm. */
667 case 'D': /* Esc O D == Left on
668 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000669 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000670 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000671 case 'E': /* Esc O E == Center (5) on numeric keypad
672 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000673 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000674 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000675 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000676 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000677 break;
678 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000679 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000680 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000681 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000682 * NumLock off on VT100/VT220/VT320/xterm/
683 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000684 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000685 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000686 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000687 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000688 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000689 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000690 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000691 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000692 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000693 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000694 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000695 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000696 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000697 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000698 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000699 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000700 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000701 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000702 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000703 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000704 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000705 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000706 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000707 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000708 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000709 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000710 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000711 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000712 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000713 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000714 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000715 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000716 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000717 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000718 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000719 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000720 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000721 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000722 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000723 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000724 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000725 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000726 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000727 * NumLock off on VT100/VT220/VT320/xterm/
728 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000729 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000730 break;
731 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000732 * NumLock off on VT100/VT220/VT320/xterm/
733 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000734 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000735 break;
736 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000737 * NumLock off on VT100/VT220/VT320/xterm/
738 * rxvt. */
David Lawrence Ramsey8f36d092005-09-24 19:42:48 +0000739 retval = ',';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000740 break;
741 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000742 * NumLock off on VT100/VT220/VT320/xterm/
743 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000744 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000745 break;
746 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000747 * with NumLock off on VT100/VT220/VT320/
748 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000749 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000750 break;
751 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000752 * NumLock off on VT100/VT220/VT320/xterm/
753 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000754 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000755 break;
756 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000757 * with NumLock off on VT100/VT220/VT320/
758 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000759 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000760 break;
761 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000762 * with NumLock off on VT100/VT220/VT320/
763 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000764 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000765 break;
766 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000767 * with NumLock off on VT100/VT220/VT320/
768 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000769 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000770 break;
771 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000772 * keypad with NumLock off on VT100/VT220/
773 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000774 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000775 break;
776 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000777 * with NumLock off on VT100/VT220/VT320/
778 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000779 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000780 break;
781 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000782 * with NumLock off on VT100/VT220/VT320/
783 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000784 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000785 break;
786 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000787 * with NumLock off on VT100/VT220/VT320/
788 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000789 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000790 break;
791 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000792 * with NumLock off on VT100/VT220/VT320/
793 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000794 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000795 break;
796 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000797 * with NumLock off on VT100/VT220/VT320/
798 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000799 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000800 break;
801 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000802 * with NumLock off on VT100/VT220/VT320/
803 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000804 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000805 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000806 }
807 break;
808 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000809 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000810 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000811 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000812 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000813 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000814 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000815 break;
816 }
817 break;
818 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000819 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000820 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000821 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000822 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000823 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
824 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000825 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000826 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000827 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
828 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000829 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000830 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000831 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
832 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000833 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000834 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000835 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
836 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000837 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000838 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000839 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
840 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000841 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000842 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000843 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000844 * VT220/VT320/Linux console/
845 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000846 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000847 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000848 case '8': /* Esc [ 1 8 ~ == F7 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(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000852 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000853 case '9': /* Esc [ 1 9 ~ == F8 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(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000857 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000858 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000859 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000860 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000861 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000862 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000863 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000864 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
865 * xterm. */
866 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
867 * xterm. */
868 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
869 * xterm. */
870 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
871 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000872 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000873 break;
874 }
875 }
876 break;
877 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000878 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000879 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000880 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
881 * xterm. */
882 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
883 * xterm. */
884 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
885 * xterm. */
886 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
887 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000888 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000889 break;
890 }
891 }
892 break;
893 }
894 }
895 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000896 default: /* Esc [ 1 ~ == Home on
897 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000898 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000899 break;
900 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000901 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000902 break;
903 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000904 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000905 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000906 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000907 * VT220/VT320/Linux console/
908 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000909 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000910 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000911 case '1': /* Esc [ 2 1 ~ == F10 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(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000915 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000916 case '3': /* Esc [ 2 3 ~ == F11 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(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000920 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000921 case '4': /* Esc [ 2 4 ~ == F12 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(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000925 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000926 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000927 * VT220/VT320/Linux console/
928 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000929 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000930 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000931 case '6': /* Esc [ 2 6 ~ == F14 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(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000935 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000936 case '8': /* Esc [ 2 8 ~ == F15 on
937 * VT220/VT320/Linux console/
938 * rxvt/Eterm. */
939 retval = KEY_F(15);
940 break;
941 case '9': /* Esc [ 2 9 ~ == F16 on
942 * VT220/VT320/Linux console/
943 * rxvt/Eterm. */
944 retval = KEY_F(16);
945 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000946 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000947 * VT220/VT320/Linux console/
948 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000949 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000950 break;
951 }
952 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000953 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000954 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
955 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000956 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000957 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000958 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000959 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000960 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000961 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000962 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
963 * Linux console/xterm; Esc [ 5 ^ ==
964 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000965 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000966 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000967 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
968 * Linux console/xterm; Esc [ 6 ^ ==
969 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000970 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000971 break;
972 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000973 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000974 break;
975 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000976 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000977 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000978 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000979 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000980 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000981 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000982 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000983 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000984 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000985 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000986 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000987 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000988 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000989 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000990 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000991 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000992 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000993 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000994 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000995 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000996 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000997 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000998 case 'E': /* Esc [ E == Center (5) on numeric keypad
999 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +00001000 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001001 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001002 case 'F': /* Esc [ F == End on FreeBSD
1003 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001004 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001005 break;
1006 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001007 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001008 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001009 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001010 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001011 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001012 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001013 break;
1014 case 'I': /* Esc [ I == PageUp on FreeBSD
1015 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001016 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001017 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001018 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001019 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001020 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001021 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001022 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001023 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001024 break;
1025 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001026 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001027 break;
1028 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001029 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001030 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001031 case 'P': /* Esc [ O P == F1 on
1032 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001033 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001034 break;
1035 case 'Q': /* Esc [ O Q == F2 on
1036 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001037 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001038 break;
1039 case 'R': /* Esc [ O R == F3 on
1040 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001041 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001042 break;
1043 case 'S': /* Esc [ O S == F4 on
1044 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001045 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001046 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001047 }
David Lawrence Ramseyec729752005-09-25 18:42:05 +00001048 } else
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001049 /* Esc [ O == F3 on FreeBSD console. */
1050 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001051 break;
1052 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001053 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001054 break;
1055 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001056 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001057 break;
1058 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001059 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001060 break;
1061 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001062 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001063 break;
1064 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001065 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001066 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001067 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001068 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001069 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001070 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001071 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001072 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001073 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001074 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001075 break;
1076 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001077 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001078 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001079 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001080 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001081 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001082 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001083 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001084 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001085 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001086 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001087 case 'c': /* Esc [ c == Shift-Right on rxvt/
1088 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001089 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001090 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001091 break;
1092 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001093 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001094 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001095 case 'A': /* Esc [ [ A == F1 on Linux
1096 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001097 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001098 break;
1099 case 'B': /* Esc [ [ B == F2 on Linux
1100 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001101 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001102 break;
1103 case 'C': /* Esc [ [ C == F3 on Linux
1104 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001105 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001106 break;
1107 case 'D': /* Esc [ [ D == F4 on Linux
1108 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001109 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001110 break;
1111 case 'E': /* Esc [ [ E == F5 on Linux
1112 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001113 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001114 break;
1115 }
1116 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001117 break;
1118 }
1119 break;
1120 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001121 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001122
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001123#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001124 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001125#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001126
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001127 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001128}
1129
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001130/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001131 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001132 * to many escape sequences. */
1133int get_escape_seq_abcd(int kbinput)
1134{
1135 switch (tolower(kbinput)) {
1136 case 'a':
1137 return NANO_PREVLINE_KEY;
1138 case 'b':
1139 return NANO_NEXTLINE_KEY;
1140 case 'c':
1141 return NANO_FORWARD_KEY;
1142 case 'd':
1143 return NANO_BACK_KEY;
1144 default:
1145 return ERR;
1146 }
1147}
1148
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001149/* Translate a byte sequence: turn a three-digit decimal number from
1150 * 000 to 255 into its corresponding byte value. */
1151int get_byte_kbinput(int kbinput
1152#ifndef NANO_SMALL
1153 , bool reset
1154#endif
1155 )
1156{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001157 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001158 int retval = ERR;
1159
1160#ifndef NANO_SMALL
1161 if (reset) {
1162 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001163 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001164 return ERR;
1165 }
1166#endif
1167
1168 /* Increment the byte digit counter. */
1169 byte_digits++;
1170
1171 switch (byte_digits) {
1172 case 1:
1173 /* One digit: reset the byte sequence holder and add the
1174 * digit we got to the 100's position of the byte sequence
1175 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001176 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001177 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001178 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001179 else
1180 /* If the character we got isn't a decimal digit, or if
1181 * it is and it would put the byte sequence out of byte
1182 * range, save it as the result. */
1183 retval = kbinput;
1184 break;
1185 case 2:
1186 /* Two digits: add the digit we got to the 10's position of
1187 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001188 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1189 '6' <= kbinput && kbinput <= '9'))
1190 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001191 else
1192 /* If the character we got isn't a decimal digit, or if
1193 * it is and it would put the byte sequence out of byte
1194 * range, save it as the result. */
1195 retval = kbinput;
1196 break;
1197 case 3:
1198 /* Three digits: add the digit we got to the 1's position of
1199 * the byte sequence holder, and save the corresponding word
1200 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001201 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1202 '6' <= kbinput && kbinput <= '9')) {
1203 byte += (kbinput - '0');
1204 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001205 } else
1206 /* If the character we got isn't a decimal digit, or if
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001207 * it is and it would put the byte sequence out of word
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001208 * range, save it as the result. */
1209 retval = kbinput;
1210 break;
1211 default:
1212 /* More than three digits: save the character we got as the
1213 * result. */
1214 retval = kbinput;
1215 break;
1216 }
1217
1218 /* If we have a result, reset the byte digit counter and the byte
1219 * sequence holder. */
1220 if (retval != ERR) {
1221 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001222 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001223 }
1224
1225#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001226 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 +00001227#endif
1228
1229 return retval;
1230}
1231
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001232/* Translate a Unicode sequence: turn a six-digit hexadecimal number
1233 * from 000000 to 10FFFF (case-insensitive) into its corresponding
1234 * multibyte value. */
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001235long get_unicode_kbinput(int kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001236#ifndef NANO_SMALL
1237 , bool reset
1238#endif
1239 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001240{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001241 static int uni_digits = 0;
1242 static long uni = 0;
1243 long retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001244
1245#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001246 if (reset) {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001247 uni_digits = 0;
1248 uni = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001249 return ERR;
1250 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001251#endif
1252
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001253 /* Increment the Unicode digit counter. */
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001254 uni_digits++;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001255
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001256 switch (uni_digits) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001257 case 1:
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001258 /* One digit: reset the Unicode sequence holder and add the
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001259 * digit we got to the 0x100000's position of the Unicode
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001260 * sequence holder. */
1261 uni = 0;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001262 if ('0' <= kbinput && kbinput <= '1')
1263 uni += (kbinput - '0') * 0x100000;
1264 else
1265 /* If the character we got isn't a hexadecimal digit, or
1266 * if it is and it would put the Unicode sequence out of
1267 * valid range, save it as the result. */
1268 retval = kbinput;
1269 break;
1270 case 2:
1271 /* Two digits: add the digit we got to the 0x10000's
1272 * position of the Unicode sequence holder. */
1273 if ('0' == kbinput || (uni < 0x100000 && '1' <= kbinput &&
1274 kbinput <= '9'))
1275 uni += (kbinput - '0') * 0x10000;
1276 else if (uni < 0x100000 && 'a' <= tolower(kbinput) &&
1277 tolower(kbinput) <= 'f')
1278 uni += (tolower(kbinput) + 10 - 'a') * 0x10000;
1279 else
1280 /* If the character we got isn't a hexadecimal digit, or
1281 * if it is and it would put the Unicode sequence out of
1282 * valid range, save it as the result. */
1283 retval = kbinput;
1284 break;
1285 case 3:
1286 /* Three digits: add the digit we got to the 0x1000's
1287 * position of the Unicode sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001288 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001289 uni += (kbinput - '0') * 0x1000;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001290 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001291 uni += (tolower(kbinput) + 10 - 'a') * 0x1000;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001292 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001293 /* If the character we got isn't a hexadecimal digit, or
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001294 * if it is and it would put the Unicode sequence out of
1295 * valid range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001296 retval = kbinput;
1297 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001298 case 4:
1299 /* Four digits: add the digit we got to the 0x100's position
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001300 * of the Unicode sequence holder. */
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001301 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001302 uni += (kbinput - '0') * 0x100;
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001303 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001304 uni += (tolower(kbinput) + 10 - 'a') * 0x100;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001305 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001306 /* If the character we got isn't a hexadecimal digit, or
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001307 * if it is and it would put the Unicode sequence out of
1308 * valid range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001309 retval = kbinput;
1310 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001311 case 5:
1312 /* Five digits: add the digit we got to the 0x10's position
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001313 * of the Unicode sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001314 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001315 uni += (kbinput - '0') * 0x10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001316 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb7bf27a2005-08-02 19:54:25 +00001317 uni += (tolower(kbinput) + 10 - 'a') * 0x10;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001318 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001319 /* If the character we got isn't a hexadecimal digit, or
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001320 * if it is and it would put the Unicode sequence out of
1321 * valid range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001322 retval = kbinput;
1323 break;
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001324 case 6:
1325 /* Six digits: add the digit we got to the 1's position of
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001326 * the Unicode sequence holder, and save the corresponding
1327 * Unicode value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001328 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001329 uni += (kbinput - '0');
1330 retval = uni;
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001331 } else if ('a' <= tolower(kbinput) && tolower(kbinput) <=
1332 'f') {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001333 uni += (tolower(kbinput) + 10 - 'a');
1334 retval = uni;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001335 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001336 /* If the character we got isn't a hexadecimal digit, or
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001337 * if it is and it would put the Unicode sequence out of
1338 * valid range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001339 retval = kbinput;
1340 break;
1341 default:
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001342 /* More than six digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001343 * result. */
1344 retval = kbinput;
1345 break;
1346 }
1347
David Lawrence Ramsey8c7a5622005-08-08 23:47:28 +00001348 /* If we have a result, reset the Unicode digit counter and the
1349 * Unicode sequence holder. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001350 if (retval != ERR) {
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001351 uni_digits = 0;
1352 uni = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001353 }
1354
1355#ifdef DEBUG
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001356 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 +00001357#endif
1358
1359 return retval;
1360}
1361
1362/* Translate a control character sequence: turn an ASCII non-control
1363 * character into its corresponding control character. */
1364int get_control_kbinput(int kbinput)
1365{
1366 int retval;
1367
1368 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1369 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1370 kbinput == '`')
1371 retval = NANO_CONTROL_SPACE;
1372 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1373 else if ('3' <= kbinput && kbinput <= '7')
1374 retval = kbinput - 24;
1375 /* Ctrl-8 (Ctrl-?) */
1376 else if (kbinput == '8' || kbinput == '?')
1377 retval = NANO_CONTROL_8;
1378 /* Ctrl-A to Ctrl-_ */
1379 else if ('A' <= kbinput && kbinput <= '_')
1380 retval = kbinput - 64;
1381 /* Ctrl-a to Ctrl-~ */
1382 else if ('a' <= kbinput && kbinput <= '~')
1383 retval = kbinput - 96;
1384 else
1385 retval = kbinput;
1386
1387#ifdef DEBUG
1388 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1389#endif
1390
1391 return retval;
1392}
1393
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001394/* Put the output-formatted characters in output back into the default
1395 * keystroke buffer, so that they can be parsed and displayed as output
1396 * again. */
1397void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001398{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001399 int *input;
1400 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001401
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001402 if (output_len == 0)
1403 return;
1404
1405 input = (int *)nmalloc(output_len * sizeof(int));
1406 for (i = 0; i < output_len; i++)
1407 input[i] = (int)output[i];
1408 unget_input(input, output_len);
1409 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001410}
1411
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001412/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001413 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1414int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1415{
1416 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001417
1418 /* Turn off flow control characters if necessary so that we can type
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001419 * them in verbatim, and turn the keypad off if necessary so that we
1420 * don't get extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001421 if (ISSET(PRESERVE))
1422 disable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001423 if (!ISSET(REBIND_KEYPAD))
1424 keypad(win, FALSE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001425
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001426 /* Read in a stream of characters and interpret it if possible. */
1427 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001428
1429 /* Turn flow control characters back on if necessary and turn the
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001430 * keypad back on if necessary now that we're done. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001431 if (ISSET(PRESERVE))
1432 enable_flow_control();
David Lawrence Ramsey057edf72005-08-10 21:22:15 +00001433 if (!ISSET(REBIND_KEYPAD))
1434 keypad(win, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001435
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001436 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001437}
1438
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001439/* Read in a stream of all available characters, and return the length
1440 * of the string in kbinput_len. Translate the first few characters of
David Lawrence Ramsey6a836472005-08-01 19:12:05 +00001441 * the input into the corresponding multibyte value if possible. After
1442 * that, leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001443int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001444{
David Lawrence Ramsey8b006c22005-08-08 23:03:25 +00001445 int *kbinput, *retval;
1446 long uni;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001447
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001448 /* Read in the first keystroke. */
1449 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001450
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001451 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001452 uni = get_unicode_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001453#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001454 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001455#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001456 );
1457
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001458 /* If the first keystroke isn't a hexadecimal digit, put back the
1459 * first keystroke. */
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001460 if (uni != ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001461 unget_input(kbinput, 1);
1462 /* Otherwise, read in keystrokes until we have a complete word
1463 * sequence, and put back the corresponding word value. */
1464 else {
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001465 char *uni_mb;
1466 int uni_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001467
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001468 while (uni == ERR) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001469 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001470
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001471 uni = get_unicode_kbinput(*kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001472#ifndef NANO_SMALL
1473 , FALSE
1474#endif
1475 );
1476 }
1477
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001478 /* Put back the multibyte equivalent of the Unicode value. */
1479 uni_mb = make_mbchar(uni, &uni_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001480
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001481 seq = (int *)nmalloc(uni_mb_len * sizeof(int));
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001482
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001483 for (i = 0; i < uni_mb_len; i++)
1484 seq[i] = (unsigned char)uni_mb[i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001485
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001486 unget_input(seq, uni_mb_len);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001487
1488 free(seq);
David Lawrence Ramsey8c55d212005-08-04 20:24:26 +00001489 free(uni_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001490 }
1491
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001492 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001493 * result. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00001494 *kbinput_len = get_key_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001495 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001496
1497 return retval;
1498}
1499
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001500#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001501/* Check for a mouse event, and if one's taken place, save the
1502 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001503 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1504 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001505 * place on it, figure out which shortcut was clicked and put back the
1506 * equivalent keystroke(s). Return FALSE if no keystrokes were
1507 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001508 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001509bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001510{
1511 MEVENT mevent;
1512
1513 *mouse_x = -1;
1514 *mouse_y = -1;
1515
1516 /* First, get the actual mouse event. */
1517 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001518 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001519
1520 /* Save the screen coordinates where the mouse event took place. */
1521 *mouse_x = mevent.x;
1522 *mouse_y = mevent.y;
1523
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001524 /* If we're allowing shortcuts, the current shortcut list is being
1525 * displayed on the last two lines of the screen, and the mouse
1526 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001527 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001528 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1529 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001530 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001531 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001532 /* The number of shortcuts in the current shortcut list. */
1533 const shortcut *s = currshortcut;
1534 /* The actual shortcut we clicked on, starting at the first
1535 * one in the current shortcut list. */
1536
1537 /* Get the shortcut lists' length. */
1538 if (currshortcut == main_list)
1539 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001540 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001541 currslen = length_of_list(currshortcut);
1542
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001543 /* We don't show any more shortcuts than the main list
1544 * does. */
1545 if (currslen > MAIN_VISIBLE)
1546 currslen = MAIN_VISIBLE;
1547 }
1548
David Lawrence Ramsey0df61f12005-06-08 20:23:06 +00001549 /* Calculate the width of each shortcut in the list. It's the
1550 * same for all of them. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001551 if (currslen < 2)
1552 i = COLS / 6;
1553 else
1554 i = COLS / ((currslen / 2) + (currslen % 2));
1555
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001556 /* Calculate the y-coordinate relative to the beginning of
David Lawrence Ramseyf7260532005-10-28 17:12:58 +00001557 * the shortcut list in bottomwin, i.e, with the sizes of
1558 * topwin, edit, and the first line of bottomwin subtracted
1559 * out. */
1560 j = *mouse_y - (2 - no_more_space()) - editwinrows - 1;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001561
1562 /* If we're on the statusbar, beyond the end of the shortcut
1563 * list, or beyond the end of a shortcut on the right side of
1564 * the screen, don't do anything. */
1565 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001566 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001567 j = (*mouse_x / i) * 2 + j;
1568 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001569 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001570
1571 /* Go through the shortcut list to determine which shortcut was
1572 * clicked. */
1573 for (; j > 0; j--)
1574 s = s->next;
1575
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001576 /* And put back the equivalent key. Assume that each shortcut
1577 * has, at the very least, an equivalent control key, an
1578 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001579 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001580 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001581 return TRUE;
1582 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001583 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001584 return TRUE;
1585 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001586 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001587 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001588}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001589#endif /* !DISABLE_MOUSE */
1590
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001591const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001592 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001593{
1594 const shortcut *s = s_list;
1595 size_t slen = length_of_list(s_list);
1596
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001597#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001598 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 +00001599#endif
1600
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001601 /* Check for shortcuts. */
1602 for (; slen > 0; slen--) {
1603 /* We've found a shortcut if:
1604 *
1605 * 1. The key exists.
1606 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001607 * 3. meta_key is TRUE and the key is the primary or
1608 * miscellaneous meta sequence in the shortcut list.
1609 * 4. func_key is TRUE and the key is a function key in the
1610 * shortcut list. */
1611
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001612 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1613 (*meta_key == TRUE && (*kbinput == s->metaval ||
1614 *kbinput == s->miscval)) || (*func_key == TRUE &&
1615 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001616 break;
1617 }
1618
1619 s = s->next;
1620 }
1621
1622 /* Translate the shortcut to either its control key or its meta key
1623 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001624 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001625 if (slen > 0) {
1626 if (s->ctrlval != NANO_NO_KEY) {
1627 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001628 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001629 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001630 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001631 } else if (s->metaval != NANO_NO_KEY) {
1632 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001633 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001634 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001635 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001636 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001637 }
1638
1639 return NULL;
1640}
1641
1642#ifndef NANO_SMALL
1643const toggle *get_toggle(int kbinput, bool meta_key)
1644{
1645 const toggle *t = toggles;
1646
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001647#ifdef DEBUG
1648 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1649#endif
1650
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001651 /* Check for toggles. */
1652 for (; t != NULL; t = t->next) {
1653 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001654 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001655 if (meta_key && kbinput == t->val)
1656 break;
1657 }
1658
1659 return t;
1660}
1661#endif /* !NANO_SMALL */
1662
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001663/* Move to (x, y) in win, and display a line of n spaces with the
1664 * current attributes. */
1665void blank_line(WINDOW *win, int y, int x, int n)
1666{
1667 wmove(win, y, x);
1668 for (; n > 0; n--)
1669 waddch(win, ' ');
1670}
1671
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001672void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001673{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001674 blank_line(topwin, 0, 0, COLS);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001675}
1676
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00001677void blank_topbar(void)
1678{
1679 if (!ISSET(MORE_SPACE))
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001680 blank_line(topwin, 1, 0, COLS);
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00001681}
1682
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001683void blank_edit(void)
1684{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001685 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001686 for (i = 0; i < editwinrows; i++)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001687 blank_line(edit, i, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001688}
1689
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001690void blank_statusbar(void)
1691{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001692 blank_line(bottomwin, 0, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001693}
1694
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00001695void blank_bottombars(void)
1696{
1697 if (!ISSET(NO_HELP)) {
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001698 blank_line(bottomwin, 1, 0, COLS);
1699 blank_line(bottomwin, 2, 0, COLS);
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00001700 }
1701}
1702
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001703void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001704{
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00001705 if (statusblank > 0)
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001706 statusblank--;
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00001707
1708 if (statusblank == 0 && !ISSET(CONST_UPDATE)) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001709 blank_statusbar();
1710 wnoutrefresh(bottomwin);
1711 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00001712 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001713 }
1714}
1715
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001716/* Convert buf into a string that can be displayed on screen. The
1717 * caller wants to display buf starting with column start_col, and
1718 * extending for at most len columns. start_col is zero-based. len is
1719 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001720 * string is dynamically allocated, and should be freed. If dollars is
1721 * TRUE, the caller might put "$" at the beginning or end of the line if
1722 * it's too long. */
1723char *display_string(const char *buf, size_t start_col, size_t len, bool
1724 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001725{
1726 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00001727 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001728 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00001729 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001730 size_t alloc_len;
1731 /* The length of memory allocated for converted. */
1732 char *converted;
1733 /* The string we return. */
1734 size_t index;
1735 /* Current position in converted. */
1736
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001737 char *buf_mb = charalloc(mb_cur_max());
1738 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001739
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00001740 /* If dollars is TRUE, make room for the "$" at the end of the
1741 * line. */
1742 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
1743 len--;
1744
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001745 if (len == 0)
1746 return mallocstrcpy(NULL, "");
1747
1748 start_index = actual_x(buf, start_col);
1749 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001750
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001751 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001752
David Lawrence Ramseyc4b854d2005-09-20 04:15:33 +00001753 /* Allocate enough space for the entire line. */
David Lawrence Ramsey86b6c3e2005-10-04 03:40:41 +00001754 alloc_len = (mb_cur_max() * (COLS + 1));
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00001755
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001756 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001757 index = 0;
1758
David Lawrence Ramsey7f26c732005-09-05 01:36:47 +00001759 if (buf[start_index] != '\t' && (column < start_col || (dollars &&
1760 column > 0))) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001761 /* We don't display all of buf[start_index] since it starts to
1762 * the left of the screen. */
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001763 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001764
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001765 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00001766 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001767 char *ctrl_buf_mb = charalloc(mb_cur_max());
1768 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001769
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001770 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
1771 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00001772
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001773 for (i = 0; i < ctrl_buf_mb_len; i++)
1774 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001775
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001776 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001777
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001778 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00001779
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001780 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001781 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00001782 }
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00001783#ifdef ENABLE_UTF8
David Lawrence Ramsey7a4aaa52005-06-16 02:09:57 +00001784 else if (ISSET(USE_UTF8) && mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00001785 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00001786 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001787
1788 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001789 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00001790#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001791 }
1792
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00001793 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001794 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001795
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00001796 /* If buf contains a tab character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001797 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001798#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001799 if (ISSET(WHITESPACE_DISPLAY)) {
1800 int i;
1801
1802 for (i = 0; i < whitespace_len[0]; i++)
1803 converted[index++] = whitespace[i];
1804 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001805#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001806 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001807 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00001808 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001809 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001810 start_col++;
1811 }
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001812 /* If buf contains a control character, interpret it. If buf
David Lawrence Ramsey61f56732005-07-21 22:12:03 +00001813 * contains an invalid multibyte control character, display it
1814 * as such.*/
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001815 } else if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001816 char *ctrl_buf_mb = charalloc(mb_cur_max());
1817 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001818
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001819 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001820 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001821
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001822 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
1823 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001824
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001825 for (i = 0; i < ctrl_buf_mb_len; i++)
1826 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001827
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001828 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001829
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001830 free(ctrl_buf_mb);
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00001831 /* If buf contains a space character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001832 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001833#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001834 if (ISSET(WHITESPACE_DISPLAY)) {
1835 int i;
1836
1837 for (i = whitespace_len[0]; i < whitespace_len[0] +
1838 whitespace_len[1]; i++)
1839 converted[index++] = whitespace[i];
1840 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001841#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00001842 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001843 start_col++;
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001844 /* If buf contains a non-control character, interpret it. If
1845 * buf contains an invalid multibyte non-control character,
1846 * display it as such. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001847 } else {
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001848 char *nctrl_buf_mb = charalloc(mb_cur_max());
1849 int nctrl_buf_mb_len, i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001850
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001851 nctrl_buf_mb = mbrep(buf_mb, nctrl_buf_mb,
1852 &nctrl_buf_mb_len);
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00001853
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001854 for (i = 0; i < nctrl_buf_mb_len; i++)
1855 converted[index++] = nctrl_buf_mb[i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001856
David Lawrence Ramsey96452cb2005-07-26 06:13:45 +00001857 start_col += mbwidth(nctrl_buf_mb);
1858
1859 free(nctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001860 }
1861
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001862 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001863 }
1864
David Lawrence Ramsey6a0d5b82005-06-13 14:00:22 +00001865 free(buf_mb);
1866
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00001867 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00001868 converted[index] = '\0';
1869
1870 /* Make sure converted takes up no more than len columns. */
1871 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001872 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00001873
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001874 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001875}
1876
Chris Allegrettaf717f982003-02-13 22:25:01 +00001877void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001878{
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001879 int space = COLS;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001880 /* The space we have available for display. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001881 size_t verlen = strlenpt(VERMSG) + 1;
1882 /* The length of the version message in columns, plus one for
1883 * padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001884 const char *prefix;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001885 /* "DIR:", "File:", or "New Buffer". Goes before filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001886 size_t prefixlen;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001887 /* The length of the prefix in columns, plus one for padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001888 const char *state;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001889 /* "Modified", "View", or "". Shows the state of this
1890 * buffer. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001891 size_t statelen = 0;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001892 /* The length of the state in columns, or the length of
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00001893 * "Modified" if the state is blank. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001894 char *exppath = NULL;
1895 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001896 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001897 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001898 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001899 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001900
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00001901 assert(path != NULL || openfile->filename != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001902
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001903 wattron(topwin, A_REVERSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001904 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001905
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001906 /* space has to be at least 4: two spaces before the version message,
1907 * at least one character of the version message, and one space
1908 * after the version message. */
1909 if (space < 4)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001910 space = 0;
1911 else {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001912 /* Limit verlen to 1/3 the length of the screen in columns,
1913 * minus three columns for spaces. */
1914 if (verlen > (COLS / 3) - 3)
1915 verlen = (COLS / 3) - 3;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001916 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001917
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001918 if (space >= 4) {
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00001919 /* Add a space after the version message, and account for both
1920 * it and the two spaces before it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001921 mvwaddnstr(topwin, 0, 2, VERMSG, actual_x(VERMSG, verlen));
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001922 verlen += 3;
1923
1924 /* Account for the full length of the version message. */
1925 space -= verlen;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001926 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001927
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001928#ifndef DISABLE_BROWSER
1929 /* Don't display the state if we're in the file browser. */
1930 if (path != NULL)
1931 state = "";
1932 else
1933#endif
1934 state = openfile->modified ? _("Modified") : ISSET(VIEW_MODE) ?
1935 _("View") : "";
1936
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00001937 statelen = strlenpt((state[0] != '\0') ? state : _("Modified"));
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00001938
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001939 /* If possible, add a space before state. */
1940 if (space > 0 && statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001941 statelen++;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001942 else
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001943 goto the_end;
1944
1945#ifndef DISABLE_BROWSER
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001946 /* path should be a directory if we're in the file browser. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001947 if (path != NULL)
1948 prefix = _("DIR:");
1949 else
1950#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00001951 if (openfile->filename[0] == '\0') {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001952 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001953 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001954 } else
1955 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00001956
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001957 prefixlen = strnlenpt(prefix, space - statelen) + 1;
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00001958
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001959 /* If newfie is FALSE, add a space after prefix. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001960 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001961 prefixlen++;
1962
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001963 /* If we're not in the file browser, path should be the current
1964 * filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001965 if (path == NULL)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00001966 path = openfile->filename;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00001967
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001968 /* Account for the full lengths of the prefix and the state. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001969 if (space >= prefixlen + statelen)
1970 space -= prefixlen + statelen;
1971 else
1972 space = 0;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001973 /* space is now the room we have for the filename. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00001974
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001975 if (!newfie) {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001976 size_t lenpt = strlenpt(path), start_col;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001977
David Lawrence Ramseya03d9c02005-09-16 17:24:22 +00001978 dots = (lenpt >= space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001979
1980 if (dots) {
1981 start_col = lenpt - space + 3;
1982 space -= 3;
1983 } else
1984 start_col = 0;
1985
1986 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001987 }
1988
1989 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001990 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
1991 /* The length of the expanded filename. */
1992
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001993 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00001994 mvwaddnstr(topwin, 0, verlen + ((space - exppathlen) / 3),
1995 prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00001996 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001997 waddch(topwin, ' ');
1998 waddstr(topwin, exppath);
1999 }
2000 } else {
2001 /* We will say something like "File: ...ename". */
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002002 mvwaddnstr(topwin, 0, verlen - 1, prefix, actual_x(prefix,
2003 prefixlen));
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002004 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002005 goto the_end;
2006 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002007 waddnstr(topwin, "...", space + 3);
2008 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002009 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002010 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002011 }
2012
2013 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002014 free(exppath);
2015
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002016 if (state[0] != '\0') {
David Lawrence Ramsey3d12f0f2005-10-26 23:14:59 +00002017 if (statelen >= COLS - 1)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002018 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
2019 else {
David Lawrence Ramseycaa86592005-07-10 23:57:32 +00002020 assert(COLS - statelen - 1 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002021
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002022 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002023 actual_x(state, statelen));
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002024 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002025 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002026
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002027 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002028
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002029 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002030 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002031 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002032}
2033
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002034/* Set the modified flag if it isn't already set, and then update the
2035 * titlebar. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002036void set_modified(void)
2037{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002038 if (!openfile->modified) {
2039 openfile->modified = TRUE;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002040 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002041 }
2042}
2043
David Lawrence Ramsey5593e202005-06-28 19:49:15 +00002044/* Display a message on the statusbar, and set disable_cursorpos to
2045 * TRUE, so that the message won't be immediately overwritten if
2046 * constant cursor position display is on. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002047void statusbar(const char *msg, ...)
2048{
2049 va_list ap;
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002050 char *bar, *foo;
2051 size_t start_x, foo_len;
2052#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2053 bool old_whitespace;
2054#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002055
2056 va_start(ap, msg);
2057
2058 /* Curses mode is turned off. If we use wmove() now, it will muck
2059 * up the terminal settings. So we just use vfprintf(). */
2060 if (curses_ended) {
2061 vfprintf(stderr, msg, ap);
2062 va_end(ap);
2063 return;
2064 }
2065
2066 /* Blank out the line. */
2067 blank_statusbar();
2068
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002069#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002070 old_whitespace = ISSET(WHITESPACE_DISPLAY);
2071 UNSET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002072#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002073 bar = charalloc(mb_cur_max() * (COLS - 3));
2074 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
2075 va_end(ap);
2076 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002077#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002078 if (old_whitespace)
2079 SET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002080#endif
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002081 free(bar);
2082 foo_len = strlenpt(foo);
2083 start_x = (COLS - foo_len - 4) / 2;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002084
David Lawrence Ramsey874703b2005-10-27 03:35:42 +00002085 wmove(bottomwin, 0, start_x);
2086 wattron(bottomwin, A_REVERSE);
2087 waddstr(bottomwin, "[ ");
2088 waddstr(bottomwin, foo);
2089 free(foo);
2090 waddstr(bottomwin, " ]");
2091 wattroff(bottomwin, A_REVERSE);
2092 wnoutrefresh(bottomwin);
2093 reset_cursor();
2094 wnoutrefresh(edit);
2095 /* Leave the cursor at its position in the edit window, not in
2096 * the statusbar. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002097
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002098 disable_cursorpos = TRUE;
David Lawrence Ramseyc6618532005-06-17 22:33:15 +00002099
2100 /* If we're doing quick statusbar blanking, and constant cursor
2101 * position display is off, blank the statusbar after only one
2102 * keystroke. Otherwise, blank it after twenty-five keystrokes,
2103 * as Pico does. */
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002104 statusblank =
2105#ifndef NANO_SMALL
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002106 ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 :
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002107#endif
2108 25;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002109}
2110
Chris Allegretta6232d662002-05-12 19:52:15 +00002111void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002112{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002113 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002114
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002115 if (ISSET(NO_HELP))
2116 return;
2117
Chris Allegretta6232d662002-05-12 19:52:15 +00002118 if (s == main_list) {
2119 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002120
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002121 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002122 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002123 slen = length_of_list(s);
2124
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002125 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002126 if (slen > MAIN_VISIBLE)
2127 slen = MAIN_VISIBLE;
2128 }
2129
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002130 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002131 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002132 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002133
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002134 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002135
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002136 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002137 const char *keystr;
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002138 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002139
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002140 /* Yucky sentinel values that we can't handle a better way. */
2141 if (s->ctrlval == NANO_CONTROL_SPACE)
2142 strcpy(foo, "^ ");
2143 else if (s->ctrlval == NANO_CONTROL_8)
2144 strcpy(foo, "^?");
2145 /* Normal values. Assume that the shortcut has an equivalent
2146 * control key, meta key sequence, or both. */
2147 else if (s->ctrlval != NANO_NO_KEY)
2148 sprintf(foo, "^%c", s->ctrlval + 64);
2149 else if (s->metaval != NANO_NO_KEY)
2150 sprintf(foo, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00002151
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002152 keystr = foo;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002153
2154 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002155 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002156 }
2157
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002158 wnoutrefresh(bottomwin);
2159 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002160 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002161}
2162
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002163/* Write a shortcut key to the help area at the bottom of the window.
2164 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2165 * to write at most len characters, even if len is very small and
2166 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2167 * the whole string! We do not bother padding the entry with blanks. */
2168void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002169{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002170 size_t keystroke_len = strlenpt(keystroke) + 1;
2171
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002172 assert(keystroke != NULL && desc != NULL);
2173
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002174 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002175 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002176 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002177
2178 if (len > keystroke_len)
2179 len -= keystroke_len;
2180 else
2181 len = 0;
2182
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002183 if (len > 0) {
2184 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002185 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002186 }
2187}
2188
David Lawrence Ramsey2b9d6a02005-11-01 17:45:31 +00002189/* Reset current_y, based on the position of current, and put the cursor
2190 * in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002191void reset_cursor(void)
2192{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002193 /* If we haven't opened any files yet, put the cursor in the top
2194 * left corner of the edit window and get out. */
David Lawrence Ramseydbcaa3b2005-07-08 20:59:24 +00002195 if (openfile == NULL) {
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002196 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002197 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002198 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002199
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002200 openfile->current_y = openfile->current->lineno -
2201 openfile->edittop->lineno;
2202 if (openfile->current_y < editwinrows) {
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002203 size_t x = xplustabs();
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002204 wmove(edit, openfile->current_y, x - get_page_start(x));
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002205 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002206}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002207
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002208/* edit_draw() takes care of the job of actually painting a line into
2209 * the edit window. fileptr is the line to be painted, at row line of
2210 * the window. converted is the actual string to be written to the
2211 * window, with tabs and control characters replaced by strings of
2212 * regular characters. start is the column number of the first
2213 * character of this page. That is, the first character of converted
2214 * corresponds to character number actual_x(fileptr->data, start) of the
2215 * line. */
2216void edit_draw(const filestruct *fileptr, const char *converted, int
2217 line, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002218{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00002219#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002220 size_t startpos = actual_x(fileptr->data, start);
2221 /* The position in fileptr->data of the leftmost character
2222 * that displays at least partially on the window. */
2223 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2224 /* The position in fileptr->data of the first character that is
2225 * completely off the window to the right.
2226 *
2227 * Note that endpos might be beyond the null terminator of the
2228 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002229#endif
2230
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002231 assert(openfile != NULL && fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002232 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002233
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002234 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002235 * just the text that needs it). */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002236 mvwaddstr(edit, line, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002237
Chris Allegretta7dd77682001-12-08 19:52:28 +00002238#ifdef ENABLE_COLOR
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002239 /* If color syntaxes are available and turned on, we need to display
2240 * them. */
2241 if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
2242 const colortype *tmpcolor = openfile->colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002243
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002244 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2245 int x_start;
2246 /* Starting column for mvwaddnstr. Zero-based. */
2247 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002248 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002249 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002250 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002251 /* Index in converted where we paint. */
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002252 regmatch_t startmatch;
2253 /* Match position for start_regex. */
2254 regmatch_t endmatch;
2255 /* Match position for end_regex. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002256
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002257 if (tmpcolor->bright)
2258 wattron(edit, A_BOLD);
2259 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002260 /* Two notes about regexec(). Return value 0 means there is
2261 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002262 * after the match. */
2263
2264 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002265 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002266 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002267
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002268 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002269 * last match. Even though two matches may overlap, we
2270 * want to ignore them, so that we can highlight
2271 * C-strings correctly. */
2272 while (k < endpos) {
2273 /* Note the fifth parameter to regexec(). It says
2274 * not to match the beginning-of-line character
2275 * unless k is 0. If regexec() returns REG_NOMATCH,
2276 * there are no more matches in the line. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002277 if (regexec(tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002278 &startmatch, (k == 0) ? 0 : REG_NOTBOL) ==
2279 REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002280 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002281 /* Translate the match to the beginning of the
2282 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002283 startmatch.rm_so += k;
2284 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002285 if (startmatch.rm_so == startmatch.rm_eo) {
2286 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002287 statusbar(
2288 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002289 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002290 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002291 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002292 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002293 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002294 x_start = strnlenpt(fileptr->data,
2295 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002296
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002297 index = actual_x(converted, x_start);
2298
2299 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00002300 strnlenpt(fileptr->data,
2301 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002302
2303 assert(0 <= x_start && 0 <= paintlen);
2304
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002305 mvwaddnstr(edit, line, x_start, converted +
2306 index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002307 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002308 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002309 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002310 } else {
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00002311 /* This is a multi-line regex. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002312 * First, we have to see if the beginning of the line is
2313 * colored by a start on an earlier line, and an end on
2314 * this line or later.
2315 *
2316 * We find the first line before fileptr matching the
2317 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002318 * end, then go to step two. Otherwise, find the next
2319 * line after start_line matching the end. If that line
2320 * is not before fileptr, then paint the beginning of
2321 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002322 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002323 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002324 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002325 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002326 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002327
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002328 while (start_line != NULL && regexec(tmpcolor->start,
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002329 start_line->data, 1, &startmatch, 0) ==
2330 REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002331 /* If there is an end on this line, there is no need
2332 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002333 if (regexec(tmpcolor->end, start_line->data, 0,
2334 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002335 goto step_two;
2336 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002337 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002338 /* No start found, so skip to the next step. */
2339 if (start_line == NULL)
2340 goto step_two;
2341 /* Now start_line is the first line before fileptr
2342 * containing a start match. Is there a start on this
2343 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002344 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002345 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002346 start_col += startmatch.rm_so;
2347 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002348 if (regexec(tmpcolor->end, start_line->data +
2349 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002350 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002351 REG_NOTBOL) == REG_NOMATCH)
2352 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002353 break;
2354 start_col++;
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002355 if (regexec(tmpcolor->start, start_line->data +
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002356 start_col, 1, &startmatch,
2357 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002358 /* No later start on this line. */
2359 goto step_two;
2360 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002361 /* Indeed, there is a start not followed on this line by
2362 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002363
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002364 /* We have already checked that there is no end before
2365 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002366 * the start at all? We don't paint unterminated
2367 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002368 end_line = fileptr;
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002369 while (end_line != NULL && regexec(tmpcolor->end,
2370 end_line->data, 1, &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002371 end_line = end_line->next;
2372
2373 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002374 if (end_line == NULL || (end_line == fileptr &&
2375 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002376 goto step_two;
2377
2378 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00002379 if (end_line != fileptr)
2380 /* If the start of fileptr is on a different line
2381 * from the end, paintlen is -1, meaning that
2382 * everything on the line gets painted. */
2383 paintlen = -1;
2384 else
2385 /* Otherwise, paintlen is the expanded location of
2386 * the end of the match minus the expanded location
2387 * of the beginning of the page. */
2388 paintlen = actual_x(converted,
2389 strnlenpt(fileptr->data, endmatch.rm_eo) -
2390 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002391
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002392 mvwaddnstr(edit, line, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002393
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002394 step_two:
2395 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002396 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002397
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002398 while (start_col < endpos) {
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002399 if (regexec(tmpcolor->start, fileptr->data +
2400 start_col, 1, &startmatch, (start_col == 0) ?
2401 0 : REG_NOTBOL) == REG_NOMATCH || start_col +
2402 startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002403 /* No more starts on this line. */
2404 break;
2405 /* Translate the match to be relative to the
2406 * beginning of the line. */
2407 startmatch.rm_so += start_col;
2408 startmatch.rm_eo += start_col;
2409
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002410 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002411 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002412 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002413 x_start = strnlenpt(fileptr->data,
2414 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002415
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002416 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002417
David Lawrence Ramsey282a9402005-07-29 21:41:04 +00002418 if (regexec(tmpcolor->end, fileptr->data +
2419 startmatch.rm_eo, 1, &endmatch,
2420 (startmatch.rm_eo == 0) ? 0 : REG_NOTBOL) ==
2421 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002422 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002423 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002424 endmatch.rm_so += startmatch.rm_eo;
2425 endmatch.rm_eo += startmatch.rm_eo;
2426 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002427 * appear on this page, and is the match more
2428 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002429 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002430 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002431 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00002432 strnlenpt(fileptr->data,
2433 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002434
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002435 assert(0 <= x_start && x_start < COLS);
2436
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002437 mvwaddnstr(edit, line, x_start, converted +
2438 index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002439 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002440 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002441 /* There is no end on this line. But we haven't
2442 * yet looked for one on later lines. */
2443 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002444
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002445 while (end_line != NULL &&
2446 regexec(tmpcolor->end, end_line->data,
2447 0, NULL, 0) == REG_NOMATCH)
2448 end_line = end_line->next;
2449
2450 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002451 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002452
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002453 mvwaddnstr(edit, line, x_start, converted +
2454 index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002455 /* We painted to the end of the line, so
2456 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002457 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002458 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002459 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002460 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002461 }
2462 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002463
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002464 wattroff(edit, A_BOLD);
2465 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002466 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002467 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002468#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002469
Chris Allegretta7dd77682001-12-08 19:52:28 +00002470#ifndef NANO_SMALL
David Lawrence Ramseydb958022005-07-13 20:18:46 +00002471 /* If the mark is on, we need to display it. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002472 if (openfile->mark_set && (fileptr->lineno <=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002473 openfile->mark_begin->lineno || fileptr->lineno <=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002474 openfile->current->lineno) && (fileptr->lineno >=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002475 openfile->mark_begin->lineno || fileptr->lineno >=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002476 openfile->current->lineno)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002477 /* fileptr is at least partially selected. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002478 const filestruct *top;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002479 /* Either current or mark_begin, whichever is first. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002480 size_t top_x;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002481 /* current_x or mark_begin_x, corresponding to top. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002482 const filestruct *bot;
2483 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002484 int x_start;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00002485 /* Starting column for mvwaddnstr(). Zero-based. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002486 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002487 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002488 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002489 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002490 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002491
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00002492 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002493
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002494 if (top->lineno < fileptr->lineno || top_x < startpos)
2495 top_x = startpos;
2496 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2497 bot_x = endpos;
2498
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002499 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002500 if (top_x < endpos && bot_x > startpos) {
2501 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002502
2503 /* x_start is the expanded location of the beginning of the
2504 * mark minus the beginning of the page. */
2505 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002506
2507 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002508 /* If the end of the mark is off the page, paintlen is
2509 * -1, meaning that everything on the line gets
2510 * painted. */
2511 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002512 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002513 /* Otherwise, paintlen is the expanded location of the
2514 * end of the mark minus the expanded location of the
2515 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002516 paintlen = strnlenpt(fileptr->data, bot_x) -
2517 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002518
2519 /* If x_start is before the beginning of the page, shift
2520 * paintlen x_start characters to compensate, and put
2521 * x_start at the beginning of the page. */
2522 if (x_start < 0) {
2523 paintlen += x_start;
2524 x_start = 0;
2525 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002526
2527 assert(x_start >= 0 && x_start <= strlen(converted));
2528
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002529 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00002530
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002531 if (paintlen > 0)
2532 paintlen = actual_x(converted + index, paintlen);
2533
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002534 wattron(edit, A_REVERSE);
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002535 mvwaddnstr(edit, line, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00002536 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002537 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002538 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002539 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002540#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002541}
2542
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002543/* Just update one line in the edit buffer. This is basically a wrapper
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002544 * for edit_draw().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002545 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002546 * If fileptr != current, then index is considered 0. The line will be
2547 * displayed starting with fileptr->data[index]. Likely args are
2548 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002549void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002550{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002551 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002552 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002553 char *converted;
2554 /* fileptr->data converted to have tabs and control characters
2555 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002556 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002557
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002558 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002559
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002560 line = fileptr->lineno - openfile->edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002561
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002562 /* We assume the line numbers are valid. Is that really true? */
2563 assert(line < 0 || line == check_linenumbers(fileptr));
2564
2565 if (line < 0 || line >= editwinrows)
2566 return;
2567
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002568 /* First, blank out the line. */
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002569 blank_line(edit, line, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002570
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002571 /* Next, convert variables that index the line to their equivalent
2572 * positions in the expanded line. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002573 index = (fileptr == openfile->current) ? strnlenpt(fileptr->data,
2574 index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002575 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002576
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002577 /* Expand the line, replacing tabs with spaces, and control
2578 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002579 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00002580
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00002581 /* Paint the line. */
David Lawrence Ramseya0aff672005-10-27 20:10:45 +00002582 edit_draw(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002583 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002584
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002585 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002586 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002587 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002588 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002589}
2590
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002591/* Return TRUE if we need an update after moving horizontally, and FALSE
2592 * otherwise. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002593 * placewewant are on different pages. */
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002594bool need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002595{
2596 return
2597#ifndef NANO_SMALL
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002598 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002599#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002600 get_page_start(old_pww) !=
2601 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002602}
2603
David Lawrence Ramseyfeb89db2005-09-13 04:45:46 +00002604/* Return TRUE if we need an update after moving vertically, and FALSE
2605 * otherwise. We need one if the mark is on or if old_pww and
2606 * placewewant are on different pages. */
2607bool need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002608{
2609 return
2610#ifndef NANO_SMALL
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002611 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002612#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002613 get_page_start(old_pww) !=
2614 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002615}
2616
2617/* Scroll the edit window in the given direction and the given number
2618 * of lines, and draw new lines on the blank lines left after the
2619 * scrolling. direction is the direction to scroll, either UP or DOWN,
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002620 * and nlines is the number of lines to scroll. We change edittop, and
David Lawrence Ramsey6969c992005-07-26 00:42:48 +00002621 * assume that current and current_x are up to date. We also assume
2622 * that scrollok(edit) is FALSE. */
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002623void edit_scroll(scroll_dir direction, ssize_t nlines)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002624{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002625 bool do_redraw = need_vertical_update(0);
David Lawrence Ramsey443a7662005-07-14 23:06:22 +00002626 const filestruct *foo;
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002627 ssize_t i;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002628
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002629 /* Don't bother scrolling less than one line. */
2630 if (nlines < 1)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002631 return;
2632
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002633 /* Part 1: nlines is the number of lines we're going to scroll the
2634 * text of the edit window. */
2635
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002636 /* Move the top line of the edit window up or down (depending on the
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002637 * value of direction) nlines lines, or as many lines as we can if
2638 * there are fewer than nlines lines available. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002639 for (i = nlines; i > 0; i--) {
2640 if (direction == UP) {
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002641 if (openfile->edittop->prev == NULL)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002642 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002643 openfile->edittop = openfile->edittop->prev;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002644 } else {
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002645 if (openfile->edittop->next == NULL)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002646 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002647 openfile->edittop = openfile->edittop->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002648 }
2649 }
2650
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00002651 /* Limit nlines to the number of lines we could scroll. */
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00002652 nlines -= i;
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00002653
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00002654 /* Don't bother scrolling zero lines or more than the number of
2655 * lines in the edit window minus one; in both cases, get out, and
2656 * in the latter case, call edit_refresh() beforehand. */
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00002657 if (nlines == 0)
2658 return;
2659
2660 if (nlines >= editwinrows) {
2661 edit_refresh();
2662 return;
2663 }
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002664
2665 /* Scroll the text of the edit window up or down nlines lines,
2666 * depending on the value of direction. */
David Lawrence Ramsey47bb8882005-07-22 22:56:03 +00002667 scrollok(edit, TRUE);
2668 wscrl(edit, (direction == UP) ? -nlines : nlines);
2669 scrollok(edit, FALSE);
2670
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00002671 /* Part 2: nlines is the number of lines in the scrolled region of
2672 * the edit window that we need to draw. */
2673
David Lawrence Ramsey68346502005-08-16 03:03:15 +00002674 /* If the top or bottom line of the file is now visible in the edit
2675 * window, we need to draw the entire edit window. */
2676 if ((direction == UP && openfile->edittop == openfile->fileage) ||
2677 (direction == DOWN && openfile->edittop->lineno + editwinrows -
2678 1 >= openfile->filebot->lineno))
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00002679 nlines = editwinrows;
David Lawrence Ramseya7f488b2005-07-17 02:19:47 +00002680
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00002681 /* If the scrolled region contains only one line, and the line
2682 * before it is visible in the edit window, we need to draw it too.
2683 * If the scrolled region contains more than one line, and the lines
2684 * before and after the scrolled region are visible in the edit
2685 * window, we need to draw them too. */
David Lawrence Ramsey2a731312005-07-24 17:06:56 +00002686 nlines += (nlines == 1) ? 1 : 2;
David Lawrence Ramseyc25ed532005-08-01 21:53:54 +00002687
David Lawrence Ramseyde0c5eb2005-07-17 22:51:44 +00002688 if (nlines > editwinrows)
2689 nlines = editwinrows;
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002690
2691 /* If we scrolled up, we're on the line before the scrolled
2692 * region. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002693 foo = openfile->edittop;
David Lawrence Ramsey14588912005-07-14 20:37:01 +00002694
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002695 /* If we scrolled down, move down to the line before the scrolled
2696 * region. */
David Lawrence Ramsey14588912005-07-14 20:37:01 +00002697 if (direction == DOWN) {
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002698 for (i = editwinrows - nlines; i > 0 && foo != NULL; i--)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002699 foo = foo->next;
2700 }
2701
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002702 /* Draw new lines on any blank lines before or inside the scrolled
2703 * region. If we scrolled down and we're on the top line, or if we
2704 * scrolled up and we're on the bottom line, the line won't be
2705 * blank, so we don't need to draw it unless the mark is on or we're
2706 * not on the first page. */
2707 for (i = nlines; i > 0 && foo != NULL; i--) {
2708 if ((i == nlines && direction == DOWN) || (i == 1 &&
2709 direction == UP)) {
2710 if (do_redraw)
2711 update_line(foo, (foo == openfile->current) ?
2712 openfile->current_x : 0);
2713 } else
2714 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00002715 openfile->current_x : 0);
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00002716 foo = foo->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002717 }
2718}
2719
2720/* Update any lines between old_current and current that need to be
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00002721 * updated. Use this if we've moved without changing any text. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002722void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002723{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002724 bool do_redraw = need_vertical_update(0) ||
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00002725 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002726 const filestruct *foo;
2727
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002728 /* If either old_current or current is offscreen, scroll the edit
2729 * window until it's onscreen and get out. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002730 if (old_current->lineno < openfile->edittop->lineno ||
2731 old_current->lineno >= openfile->edittop->lineno +
2732 editwinrows || openfile->current->lineno <
2733 openfile->edittop->lineno || openfile->current->lineno >=
2734 openfile->edittop->lineno + editwinrows) {
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002735 filestruct *old_edittop = openfile->edittop;
2736 ssize_t nlines;
2737
2738 /* Put edittop in range of current, get the difference in lines
2739 * between the original edittop and the current edittop, and
2740 * then restore the original edittop. */
2741 edit_update(
2742#ifndef NANO_SMALL
2743 ISSET(SMOOTH_SCROLL) ? NONE :
2744#endif
2745 CENTER);
2746
2747 nlines = openfile->edittop->lineno - old_edittop->lineno;
2748
2749 openfile->edittop = old_edittop;
2750
David Lawrence Ramsey258497f2005-08-01 21:17:38 +00002751 /* Scroll the edit window up or down until edittop is in range
2752 * of current. */
David Lawrence Ramsey107e8162005-08-01 21:05:29 +00002753 if (nlines < 0)
2754 edit_scroll(UP, -nlines);
2755 else
2756 edit_scroll(DOWN, nlines);
2757
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002758 return;
2759 }
2760
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00002761 /* Update old_current and current if we're not on the first page
2762 * and/or we're not on the same page as before. If the mark is on,
2763 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002764 foo = old_current;
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00002765
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002766 while (foo != openfile->current) {
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002767 if (do_redraw)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002768 update_line(foo, 0);
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00002769
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002770#ifndef NANO_SMALL
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002771 if (!openfile->mark_set)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002772#endif
2773 break;
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00002774
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002775#ifndef NANO_SMALL
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00002776 foo = (foo->lineno > openfile->current->lineno) ? foo->prev :
2777 foo->next;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002778#endif
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002779 }
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00002780
David Lawrence Ramsey27865302005-07-23 20:39:41 +00002781 if (do_redraw)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002782 update_line(openfile->current, openfile->current_x);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002783}
2784
David Lawrence Ramsey75a29b72005-07-26 14:26:47 +00002785/* Refresh the screen without changing the position of lines. Use this
2786 * if we've moved and changed text. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002787void edit_refresh(void)
2788{
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002789 const filestruct *foo;
2790 int nlines;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002791
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002792 if (openfile->current->lineno < openfile->edittop->lineno ||
2793 openfile->current->lineno >= openfile->edittop->lineno +
2794 editwinrows)
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002795 /* Put the top line of the edit window in range of the current
2796 * line. */
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002797 edit_update(
2798#ifndef NANO_SMALL
David Lawrence Ramseyb2b69762005-06-16 02:13:10 +00002799 ISSET(SMOOTH_SCROLL) ? NONE :
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002800#endif
2801 CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002802
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002803 foo = openfile->edittop;
2804
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002805#ifdef DEBUG
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002806 fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", (long)openfile->edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002807#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002808
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002809 for (nlines = 0; nlines < editwinrows && foo != NULL; nlines++) {
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002810 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002811 openfile->current_x : 0);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002812 foo = foo->next;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002813 }
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002814
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002815 for (; nlines < editwinrows; nlines++)
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002816 blank_line(edit, nlines, 0, COLS);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002817
2818 reset_cursor();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002819 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002820}
2821
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002822/* Move edittop to put it in range of current, keeping current in the
2823 * same place. location determines how we move it: if it's CENTER, we
2824 * center current, and if it's NONE, we put current current_y lines
2825 * below edittop. */
David Lawrence Ramseybf0e47d2005-08-01 18:27:10 +00002826void edit_update(update_type location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002827{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002828 filestruct *foo = openfile->current;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002829 int goal;
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00002830
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002831 /* If location is CENTER, we move edittop up (editwinrows / 2)
2832 * lines. This puts current at the center of the screen. If
2833 * location is NONE, we move edittop up current_y lines if current_y
2834 * is in range of the screen, 0 lines if current_y is less than 0,
2835 * or (editwinrows - 1) lines if current_y is greater than
2836 * (editwinrows - 1). This puts current at the same place on the
2837 * screen as before, or at the top or bottom of the screen if
2838 * edittop is beyond either. */
2839 if (location == CENTER)
2840 goal = editwinrows / 2;
2841 else {
2842 goal = openfile->current_y;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002843
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002844 /* Limit goal to (editwinrows - 1) lines maximum. */
2845 if (goal > editwinrows - 1)
2846 goal = editwinrows - 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002847 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00002848
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00002849 for (; goal > 0 && foo->prev != NULL; goal--)
2850 foo = foo->prev;
2851
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002852 openfile->edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002853}
2854
David Lawrence Ramsey52453442004-06-26 15:24:16 +00002855/* Ask a simple yes/no question, specified in msg, on the statusbar.
2856 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
2857 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002858int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002859{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002860 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00002861 const char *yesstr; /* String of yes characters accepted. */
2862 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002863 const char *allstr; /* And all, surprise! */
David Lawrence Ramsey3f301dd2005-06-21 19:47:39 +00002864
2865 assert(msg != NULL);
Chris Allegretta235ab192001-04-12 13:24:40 +00002866
David Lawrence Ramsey52453442004-06-26 15:24:16 +00002867 /* yesstr, nostr, and allstr are strings of any length. Each string
David Lawrence Ramseydcb4e3a2005-04-08 20:27:02 +00002868 * consists of all single-byte characters accepted as valid
2869 * characters for that value. The first value will be the one
2870 * displayed in the shortcuts. Translators: if possible, specify
2871 * both the shortcuts for your language and English. For example,
2872 * in French: "OoYy" for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002873 yesstr = _("Yy");
2874 nostr = _("Nn");
2875 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002876
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002877 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002878 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00002879
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002880 if (COLS < 32)
2881 width = COLS / 2;
2882
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002883 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00002884 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002885
Chris Allegretta6232d662002-05-12 19:52:15 +00002886 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00002887 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002888 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002889
2890 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002891 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00002892 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002893 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002894 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002895
Chris Allegrettadb28e962003-01-28 01:23:40 +00002896 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00002897 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002898 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002899
Chris Allegrettadb28e962003-01-28 01:23:40 +00002900 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002901 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002902 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00002903
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002904 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002905
2906 blank_statusbar();
David Lawrence Ramseyd4ea5b62005-06-21 21:03:06 +00002907 mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
Chris Allegretta8ce24132001-04-30 11:28:46 +00002908
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002909 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002910
David Lawrence Ramsey73bf89f2005-06-30 05:56:39 +00002911 /* Refresh the edit window and the statusbar before getting
2912 * input. */
2913 wnoutrefresh(edit);
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00002914 wnoutrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002915
Chris Allegrettadb28e962003-01-28 01:23:40 +00002916 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002917 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00002918 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00002919#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002920 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00002921#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002922
David Lawrence Ramsey44e0c032005-06-29 19:01:11 +00002923 kbinput = get_kbinput(bottomwin, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002924
David Lawrence Ramseyda331532005-06-06 17:00:08 +00002925 if (kbinput == NANO_REFRESH_KEY) {
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00002926 total_redraw();
David Lawrence Ramseyda331532005-06-06 17:00:08 +00002927 continue;
2928 } else if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00002929 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00002930#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002931 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00002932 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002933
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002934 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00002935 wenclose(bottomwin, mouse_y, mouse_x) &&
2936 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002937 int x = mouse_x / width;
2938 /* Did we click in the first column of shortcuts, or
2939 * the second? */
2940 int y = mouse_y - editwinrows - 3;
2941 /* Did we click in the first row of shortcuts? */
2942
2943 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
2944
2945 /* x = 0 means they clicked Yes or No.
2946 * y = 0 means Yes or All. */
2947 ok = -2 * x * y + x - y + 1;
2948
2949 if (ok == 2 && !all)
2950 ok = -2;
2951 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002952 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00002953#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002954 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00002955 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00002956 else if (strchr(yesstr, kbinput) != NULL)
2957 ok = 1;
2958 else if (strchr(nostr, kbinput) != NULL)
2959 ok = 0;
2960 else if (all && strchr(allstr, kbinput) != NULL)
2961 ok = 2;
2962 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002963
Chris Allegrettadb28e962003-01-28 01:23:40 +00002964 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002965}
2966
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00002967void total_redraw(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002968{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002969#ifdef USE_SLANG
2970 /* Slang curses emulation brain damage, part 3: Slang doesn't define
2971 * curscr. */
2972 SLsmg_touch_screen();
2973 SLsmg_refresh();
2974#else
2975 wrefresh(curscr);
2976#endif
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002977}
2978
2979void total_refresh(void)
2980{
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00002981 total_redraw();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002982 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00002983 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002984 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002985}
2986
2987void display_main_list(void)
2988{
2989 bottombars(main_list);
2990}
2991
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00002992/* If constant is TRUE, we display the current cursor position only if
2993 * disable_cursorpos is FALSE. Otherwise, we display it
2994 * unconditionally and set disable_cursorpos to FALSE. If constant is
2995 * TRUE and disable_cursorpos is TRUE, we also set disable_cursorpos to
2996 * FALSE, so that we leave the current statusbar alone this time, and
2997 * display the current cursor position next time. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00002998void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002999{
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003000 filestruct *f;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003001 char c;
David Lawrence Ramsey5745c0a2005-07-31 20:20:37 +00003002 size_t i, cur_xpt = xplustabs() + 1;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003003 size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003004 int linepct, colpct, charpct;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003005
David Lawrence Ramsey4ab80152005-07-31 18:51:51 +00003006 assert(openfile->fileage != NULL && openfile->current != NULL);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003007
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003008 f = openfile->current->next;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003009 c = openfile->current->data[openfile->current_x];
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003010
3011 openfile->current->next = NULL;
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003012 openfile->current->data[openfile->current_x] = '\0';
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003013
3014 i = get_totsize(openfile->fileage, openfile->current);
3015
David Lawrence Ramsey15d68572005-07-31 20:15:01 +00003016 openfile->current->data[openfile->current_x] = c;
David Lawrence Ramsey04f65f22005-08-01 02:18:05 +00003017 openfile->current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003018
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003019 /* Check whether totsize is correct. If it isn't, there is a bug
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003020 * somewhere. */
David Lawrence Ramsey7fc0ada2005-08-29 18:52:06 +00003021 assert(openfile->current != openfile->filebot || i == openfile->totsize);
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003022
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003023 if (constant && disable_cursorpos) {
3024 disable_cursorpos = FALSE;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003025 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003026 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003027
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003028 /* Display the current cursor position on the statusbar, and set
3029 * disable_cursorpos to FALSE. */
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003030 linepct = 100 * openfile->current->lineno /
3031 openfile->filebot->lineno;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003032 colpct = 100 * cur_xpt / cur_lenpt;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003033 charpct = (openfile->totsize == 0) ? 0 : 100 * i /
3034 openfile->totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003035
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003036 statusbar(
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003037 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003038 (long)openfile->current->lineno,
David Lawrence Ramsey520a90c2005-07-25 21:23:11 +00003039 (long)openfile->filebot->lineno, linepct,
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003040 (unsigned long)cur_xpt, (unsigned long)cur_lenpt, colpct,
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003041 (unsigned long)i, (unsigned long)openfile->totsize, charpct);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003042
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003043 disable_cursorpos = FALSE;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003044}
3045
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003046void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003047{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003048 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003049}
3050
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003051#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003052/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003053size_t help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003054{
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003055 int help_cols = (COLS > 24) ? COLS - 8 : 24;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003056
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003057 /* Try to break the line at (COLS - 8) columns if we have more than
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003058 * 24 columns, and at 24 columns otherwise. */
David Lawrence Ramsey40e211b2005-03-19 21:15:30 +00003059 size_t retval = break_line(ptr, help_cols, TRUE);
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003060 size_t retval_save = retval;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003061
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003062 /* Get the length of the entire line up to a null or a newline. */
3063 while (*(ptr + retval) != '\0' && *(ptr + retval) != '\n')
3064 retval += move_mbright(ptr + retval, 0);
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003065
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003066 /* If the entire line doesn't go more than 8 columns beyond where we
3067 * tried to break it, we should display it as-is. Otherwise, we
3068 * should display it only up to the break. */
3069 if (strnlenpt(ptr, retval) > help_cols + 8)
3070 retval = retval_save;
3071
3072 return retval;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003073}
3074
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003075/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003076void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003077{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003078 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003079 /* The line number in help_text of the first displayed help
3080 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003081 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003082 /* no_more means the end of the help text is shown, so don't go
3083 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003084 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003085 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003086
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003087 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003088#ifndef DISABLE_MOUSE
3089 const shortcut *oldshortcut = currshortcut;
3090 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003091 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003092#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003093
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003094 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003095 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003096 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003097 blank_statusbar();
3098
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003099 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003100 help_init();
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003101
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003102 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003103
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003104#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003105 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003106 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003107 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003108#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003109
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003110 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003111 /* Make sure that the help screen's shortcut list will actually
3112 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003113 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003114 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003115 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003116
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003117 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003118
3119 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003120 int i;
3121 int old_line = line;
3122 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003123 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003124
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003125 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003126#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003127 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003128 {
3129 int mouse_x, mouse_y;
3130 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3131 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003132 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003133#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003134 case NANO_PREVPAGE_KEY:
3135 case NANO_PREVPAGE_FKEY:
3136 if (line > 0) {
3137 line -= editwinrows - 2;
3138 if (line < 0)
3139 line = 0;
3140 }
3141 break;
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003142 case NANO_NEXTPAGE_KEY:
3143 case NANO_NEXTPAGE_FKEY:
3144 if (!no_more)
3145 line += editwinrows - 2;
3146 break;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003147 case NANO_PREVLINE_KEY:
3148 if (line > 0)
3149 line--;
3150 break;
3151 case NANO_NEXTLINE_KEY:
3152 if (!no_more)
3153 line++;
3154 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003155 }
3156
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003157 if (kbinput == NANO_REFRESH_KEY)
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003158 total_redraw();
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003159 else {
3160 if (line == old_line && kbinput != ERR)
3161 goto skip_redisplay;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003162
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003163 blank_edit();
3164 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003165
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003166 /* Calculate where in the text we should be, based on the
3167 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003168 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003169 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003170 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003171 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003172 }
3173
Chris Allegretta4640fe32003-02-10 03:10:03 +00003174 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003175 size_t j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003176
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003177 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003178 ptr += j;
3179 if (*ptr == '\n')
3180 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003181 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003182 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003183
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003184 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003185 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003186 } while (kbinput != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003187
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003188#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003189 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003190#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003191
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003192 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003193 blank_bottombars();
David Lawrence Ramsey6d8e4952005-07-26 14:42:57 +00003194 wnoutrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003195 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003196 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003197 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003198 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003199
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003200 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003201 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003202
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003203 /* The help_init() at the beginning allocated help_text. Since
3204 * help_text has now been written to the screen, we don't need it
3205 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003206 free(help_text);
3207 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003208}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003209#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003210
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003211/* Highlight the current word being replaced or spell checked. We
3212 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003213void do_replace_highlight(bool highlight, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003214{
David Lawrence Ramsey6168cb72005-06-30 03:53:28 +00003215 size_t y = xplustabs(), word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003216
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003217 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003218 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003219 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003220
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003221 assert(y > 0);
3222
3223 if (word_len > y)
3224 y--;
3225
Chris Allegrettafb62f732000-12-05 11:36:41 +00003226 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003227
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003228 if (highlight)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003229 wattron(edit, A_REVERSE);
3230
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003231#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003232 /* This is so we can show zero-length regexes. */
3233 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00003234 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003235 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003236#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003237 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003238
3239 if (word_len > y)
3240 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003241
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00003242 if (highlight)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003243 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003244}
3245
David Lawrence Ramseycc814362005-06-05 19:08:59 +00003246#ifndef NDEBUG
3247/* Return what the current line number should be, starting at edittop
3248 * and ending at fileptr. */
3249int check_linenumbers(const filestruct *fileptr)
3250{
3251 int check_line = 0;
3252 const filestruct *filetmp;
3253
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003254 for (filetmp = openfile->edittop; filetmp != fileptr;
3255 filetmp = filetmp->next)
David Lawrence Ramseycc814362005-06-05 19:08:59 +00003256 check_line++;
3257
3258 return check_line;
3259}
David Lawrence Ramsey37dd7752005-10-04 03:41:32 +00003260#endif /* !NDEBUG */
David Lawrence Ramseycc814362005-06-05 19:08:59 +00003261
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003262#ifdef DEBUG
David Lawrence Ramsey1e64db62005-06-14 23:38:41 +00003263/* Dump the filestruct inptr to stderr. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003264void dump_filestruct(const filestruct *inptr)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003265{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003266 if (inptr == openfile->fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003267 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003268 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003269 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003270 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003271 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003272
3273 while (inptr != NULL) {
David Lawrence Ramsey2cf6d712005-06-28 06:25:34 +00003274 fprintf(stderr, "(%ld) %s\n", (long)inptr->lineno, inptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003275 inptr = inptr->next;
3276 }
3277}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003278
David Lawrence Ramsey4c221672005-07-17 15:40:49 +00003279/* Dump the current buffer's filestruct to stderr in reverse. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003280void dump_filestruct_reverse(void)
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00003281{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003282 const filestruct *fileptr = openfile->filebot;
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003283
3284 while (fileptr != NULL) {
David Lawrence Ramsey2cf6d712005-06-28 06:25:34 +00003285 fprintf(stderr, "(%ld) %s\n", (long)fileptr->lineno,
3286 fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003287 fileptr = fileptr->prev;
3288 }
3289}
3290#endif /* DEBUG */
3291
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003292#ifdef NANO_EXTRA
David Lawrence Ramsey20d3cb02005-08-29 18:51:27 +00003293#define CREDIT_LEN 54
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003294#define XLCREDIT_LEN 8
3295
David Lawrence Ramsey8ad58bc2005-08-16 03:02:46 +00003296/* Easter egg: Display credits. Assume nodelay(edit) and scrollok(edit)
3297 * are FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003298void do_credits(void)
3299{
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003300 bool old_more_space = ISSET(MORE_SPACE);
3301 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003302 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003303 const char *credits[CREDIT_LEN] = {
3304 NULL, /* "The nano text editor" */
3305 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003306 VERSION,
3307 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003308 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003309 "Chris Allegretta",
3310 "Jordi Mallach",
3311 "Adam Rogoyski",
3312 "Rob Siemborski",
3313 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003314 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003315 "David Benbennick",
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003316 "Mike Frysinger",
Chris Allegretta598106e2002-01-19 01:59:37 +00003317 "Ken Tyler",
3318 "Sven Guckes",
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003319 NULL, /* credits[15], handled below. */
Chris Allegretta598106e2002-01-19 01:59:37 +00003320 "Pauli Virtanen",
3321 "Daniele Medri",
3322 "Clement Laforet",
3323 "Tedi Heriyanto",
3324 "Bill Soudan",
3325 "Christian Weisgerber",
3326 "Erik Andersen",
3327 "Big Gaute",
3328 "Joshua Jensen",
3329 "Ryan Krebs",
3330 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003331 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003332 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003333 "Plattsburgh State University",
3334 "Benet Laboratories",
3335 "Amy Allegretta",
3336 "Linda Young",
3337 "Jeremy Robichaud",
3338 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003339 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003340 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003341 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003342 "Thomas Dickey",
3343 "Pavel Curtis",
3344 "Zeyd Ben-Halim",
3345 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003346 NULL, /* "and anyone else we forgot..." */
3347 NULL, /* "Thank you for using nano!" */
3348 "",
3349 "",
3350 "",
3351 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00003352 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003353 "",
3354 "",
3355 "",
3356 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003357 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003358 };
3359
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003360 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003361 N_("The nano text editor"),
3362 N_("version"),
3363 N_("Brought to you by:"),
3364 N_("Special thanks to:"),
3365 N_("The Free Software Foundation"),
3366 N_("For ncurses:"),
3367 N_("and anyone else we forgot..."),
3368 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003369 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003370
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003371 /* credits[15]: Make sure this name is displayed properly, since we
David Lawrence Ramsey62d616b2005-07-06 19:20:32 +00003372 * can't dynamically assign it above, using Unicode 00F6 (Latin
3373 * Small Letter O with Diaresis) if applicable. */
David Lawrence Ramsey47daf022005-08-29 18:29:02 +00003374 credits[15] =
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00003375#ifdef ENABLE_UTF8
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003376 ISSET(USE_UTF8) ? "Florian K\xC3\xB6nig" :
3377#endif
3378 "Florian K\xF6nig";
3379
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003380 if (!old_more_space || !old_no_help) {
3381 SET(MORE_SPACE);
3382 SET(NO_HELP);
3383 window_init();
3384 }
3385
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003386 curs_set(0);
3387 nodelay(edit, TRUE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003388
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003389 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003390 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003391 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003392 blank_statusbar();
3393 blank_bottombars();
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003394
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003395 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003396 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003397 wrefresh(bottomwin);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003398 napms(700);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003399
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003400 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003401 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003402 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003403
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003404 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003405 const char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003406 size_t start_x;
3407
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003408 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003409 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003410
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003411 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003412 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003413 } else
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00003414 what = credits[crpos];
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003415
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003416 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00003417 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
3418 start_x, what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003419 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00003420
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003421 wrefresh(edit);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003422
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003423 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003424 break;
3425 napms(700);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003426
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003427 scrollok(edit, TRUE);
David Lawrence Ramseyc71e0312005-08-14 21:17:37 +00003428 wscrl(edit, 1);
3429 scrollok(edit, FALSE);
3430 wrefresh(edit);
3431
3432 if ((kbinput = wgetch(edit)) != ERR)
3433 break;
3434 napms(700);
3435
3436 scrollok(edit, TRUE);
3437 wscrl(edit, 1);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003438 scrollok(edit, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003439 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003440 }
3441
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003442 if (kbinput != ERR)
3443 ungetch(kbinput);
3444
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003445 if (!old_more_space || !old_no_help) {
3446 UNSET(MORE_SPACE);
3447 UNSET(NO_HELP);
3448 window_init();
3449 }
3450
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00003451 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003452 nodelay(edit, FALSE);
David Lawrence Ramsey31de1052005-08-14 19:25:16 +00003453
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003454 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003455}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003456#endif