blob: 74dbcad9ddffce2a3a2d73784d542a91ca71425f [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 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
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 *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
Jordi Mallach55381aa2004-11-17 23:17:05 +000022#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000025
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000026#include <stdarg.h>
27#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000028#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000029#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000030#include <ctype.h>
Chris Allegretta6232d662002-05-12 19:52:15 +000031#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000032#include "proto.h"
33#include "nano.h"
34
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. */
42static int statusblank = 0; /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000043 * we call statusbar(), before we
44 * actually blank the statusbar. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +000045static size_t statusbar_x = (size_t)-1;
46 /* The cursor position in answer. */
47static size_t statusbar_xend = 0;
48 /* The length of answer. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000049static bool resetstatuspos = FALSE;
50 /* Should we reset the cursor position
51 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000052
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000053/* Control character compatibility:
54 *
55 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
56 * VT100, and VT220.
57 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
58 * VT220, and VT320.
59 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
60 * VT220, and VT320.
61 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
62 * VT220, and VT320.
63 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
64 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000065 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000066 * ANSI, VT100, and VT220, and which is Backspace under VT320.
67 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000068 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000069 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
70 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000071 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000072 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000073 * on which the VT320 sequences are translated by the keypad to KEY_DC
74 * and [nothing]. We work around this conflict via the REBIND_DELETE
75 * flag: if it's not set, we assume VT320 compatibility, and if it is,
76 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
77 * Hemel for helping work this conflict out.
78 *
79 * Escape sequence compatibility:
80 *
81 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000082 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000083 * console), xterm, rxvt, and Eterm. Among these, there are several
84 * conflicts and omissions, outlined as follows:
85 *
86 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
87 * (Ctrl-I is also Tab on ANSI, which we already support.)
88 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
89 * NumLock off on Linux console; the latter is omitted. (The editing
90 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000091 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000092 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
93 * latter is omitted. (Mouse input will only work properly if the
94 * extended keypad value KEY_MOUSE is generated on mouse events
95 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000096 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000097 * omitted. (The editing keypad is more important to have working
98 * than the function keys, because the functions of the former are not
99 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000100 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000101 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000102 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000103 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000104 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
105 * omitted. (The arrow keys, with or without modifiers, are more
106 * important to have working than the function keys, because the
107 * functions of the former are not arbitrary and the functions of the
108 * latter are.)
109 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
110 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000111 *
112 * Note that Center (5) on the numeric keypad with NumLock off can also
113 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000114
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000115#ifndef NANO_SMALL
116/* Reset all the input routines that rely on character sequences. */
117void reset_kbinput(void)
118{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000119 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000120 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000121 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000122}
123#endif
124
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000125/* Read in a sequence of keystrokes from win and save them in the
126 * default keystroke buffer. This should only be called when the
127 * default keystroke buffer is empty. */
128void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000129{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000130 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000131
132 /* If the keystroke buffer isn't empty, get out. */
133 if (key_buffer != NULL)
134 return;
135
136 /* Read in the first character using blocking input. */
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000137#ifndef NANO_SMALL
138 allow_pending_sigwinch(TRUE);
139#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000140
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000141 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000142
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000143#ifndef NANO_SMALL
144 allow_pending_sigwinch(FALSE);
145#endif
146
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000147 /* Increment the length of the keystroke buffer, save the value of
148 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000149 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000150 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000151 key_buffer = (int *)nmalloc(sizeof(int));
152 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000153
154 /* Read in the remaining characters using non-blocking input. */
155 nodelay(win, TRUE);
156
157 while (TRUE) {
158#ifndef NANO_SMALL
159 allow_pending_sigwinch(TRUE);
160#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000161
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000162 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000163
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000164 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000165 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000166 break;
167
168 /* Otherwise, increment the length of the keystroke buffer, save
169 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000170 * if the keystroke is an extended keypad value or FALSE if it
171 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000172 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000173 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
174 sizeof(int));
175 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000176
177#ifndef NANO_SMALL
178 allow_pending_sigwinch(FALSE);
179#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000180 }
181
182 /* Switch back to non-blocking input. */
183 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000184}
185
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000186/* Return the length of the default keystroke buffer. */
187size_t get_buffer_len(void)
188{
189 return key_buffer_len;
190}
191
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000192/* Add the contents of the keystroke buffer input to the default
193 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000194void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000195{
196#ifndef NANO_SMALL
197 allow_pending_sigwinch(TRUE);
198 allow_pending_sigwinch(FALSE);
199#endif
200
201 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000202 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000203 return;
204
205 /* If adding input would put the default keystroke buffer beyond
206 * maximum capacity, only add enough of input to put it at maximum
207 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000208 if (key_buffer_len + input_len < key_buffer_len)
209 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000210
211 /* Add the length of input to the length of the default keystroke
212 * buffer, and reallocate the default keystroke buffer so that it
213 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000214 key_buffer_len += input_len;
215 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
216 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000217
218 /* If the default keystroke buffer wasn't empty before, move its
219 * beginning forward far enough so that we can add input to its
220 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000221 if (key_buffer_len > input_len)
222 memmove(key_buffer + input_len, key_buffer,
223 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000224
225 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000226 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000227}
228
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000229/* Put back the character stored in kbinput, putting it in byte range
230 * beforehand. If meta_key is TRUE, put back the Escape character after
231 * putting back kbinput. If func_key is TRUE, put back the function key
232 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000233void unget_kbinput(int kbinput, bool meta_key, bool func_key)
234{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000235 if (!func_key)
236 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000237
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000238 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000239
240 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000241 kbinput = NANO_CONTROL_3;
242 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000243 }
244}
245
246/* Try to read input_len characters from the default keystroke buffer.
247 * If the default keystroke buffer is empty and win isn't NULL, try to
248 * read in more characters from win and add them to the default
249 * keystroke buffer before doing anything else. If the default
250 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000251int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000252{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000253 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000254
255#ifndef NANO_SMALL
256 allow_pending_sigwinch(TRUE);
257 allow_pending_sigwinch(FALSE);
258#endif
259
260 if (key_buffer_len == 0) {
261 if (win != NULL)
262 get_buffer(win);
263
264 if (key_buffer_len == 0)
265 return NULL;
266 }
267
268 /* If input_len is greater than the length of the default keystroke
269 * buffer, only read the number of characters in the default
270 * keystroke buffer. */
271 if (input_len > key_buffer_len)
272 input_len = key_buffer_len;
273
274 /* Subtract input_len from the length of the default keystroke
275 * buffer, and allocate the keystroke buffer input so that it
276 * has enough room for input_len keystrokes. */
277 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000278 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000279
280 /* Copy input_len characters from the beginning of the default
281 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000282 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000283
284 /* If the default keystroke buffer is empty, mark it as such. */
285 if (key_buffer_len == 0) {
286 free(key_buffer);
287 key_buffer = NULL;
288 /* If the default keystroke buffer isn't empty, move its
289 * beginning forward far enough back so that the keystrokes in input
290 * are no longer at its beginning. */
291 } else {
292 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000293 sizeof(int));
294 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
295 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000296 }
297
298 return input;
299}
300
301/* Read in a single character. If it's ignored, swallow it and go on.
302 * Otherwise, try to translate it from ASCII, meta key sequences, escape
303 * sequences, and/or extended keypad values. Set meta_key to TRUE when
304 * we get a meta key sequence, and set func_key to TRUE when we get an
305 * extended keypad value. Supported extended keypad values consist of
306 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
307 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
308 * the function keypad (F1-F16), and the numeric keypad with NumLock
309 * off. Assume nodelay(win) is FALSE. */
310int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
311{
312 int kbinput;
313
314 /* Read in a character and interpret it. Continue doing this until
315 * we get a recognized value or sequence. */
316 while ((kbinput = parse_kbinput(win, meta_key, func_key
317#ifndef NANO_SMALL
318 , FALSE
319#endif
320 )) == ERR);
321
322 return kbinput;
323}
324
325/* Translate ASCII characters, extended keypad values, and escape
326 * sequences into their corresponding key values. Set meta_key to TRUE
327 * when we get a meta key sequence, and set func_key to TRUE when we get
328 * a function key. Assume nodelay(win) is FALSE. */
329int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000330#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000331 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000332#endif
333 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000334
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000335{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000336 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000337 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000338
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000339#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000340 if (reset) {
341 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000342 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000343 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000344 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000345#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000346
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000347 *meta_key = FALSE;
348 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000349
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000350 /* Read in a character. */
351 while ((kbinput = get_input(win, 1)) == NULL);
352
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000353 switch (*kbinput) {
354 case ERR:
355 break;
356 case NANO_CONTROL_3:
357 /* Increment the escape counter. */
358 escapes++;
359 switch (escapes) {
360 case 1:
361 /* One escape: wait for more input. */
362 case 2:
363 /* Two escapes: wait for more input. */
364 break;
365 default:
366 /* More than two escapes: reset the escape counter
367 * and wait for more input. */
368 escapes = 0;
369 }
370 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000371#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000372 /* Since we don't change the default SIGWINCH handler when
373 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
374 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
375 case KEY_RESIZE:
376 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000377#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000378#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000379 case KEY_SHIFT_L:
380 case KEY_SHIFT_R:
381 case KEY_CONTROL_L:
382 case KEY_CONTROL_R:
383 case KEY_ALT_L:
384 case KEY_ALT_R:
385 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000386#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000387 default:
388 switch (escapes) {
389 case 0:
390 switch (*kbinput) {
391 case NANO_CONTROL_8:
392 retval = ISSET(REBIND_DELETE) ?
393 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
394 break;
395 case KEY_DOWN:
396 retval = NANO_NEXTLINE_KEY;
397 break;
398 case KEY_UP:
399 retval = NANO_PREVLINE_KEY;
400 break;
401 case KEY_LEFT:
402 retval = NANO_BACK_KEY;
403 break;
404 case KEY_RIGHT:
405 retval = NANO_FORWARD_KEY;
406 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000407#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000408 /* HP-UX 10 and 11 don't support KEY_HOME. */
409 case KEY_HOME:
410 retval = NANO_HOME_KEY;
411 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000412#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000413 case KEY_BACKSPACE:
414 retval = NANO_BACKSPACE_KEY;
415 break;
416 case KEY_DC:
417 retval = ISSET(REBIND_DELETE) ?
418 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
419 break;
420 case KEY_IC:
421 retval = NANO_INSERTFILE_KEY;
422 break;
423 case KEY_NPAGE:
424 retval = NANO_NEXTPAGE_KEY;
425 break;
426 case KEY_PPAGE:
427 retval = NANO_PREVPAGE_KEY;
428 break;
429 case KEY_ENTER:
430 retval = NANO_ENTER_KEY;
431 break;
432 case KEY_A1: /* Home (7) on numeric keypad
433 * with NumLock off. */
434 retval = NANO_HOME_KEY;
435 break;
436 case KEY_A3: /* PageUp (9) on numeric keypad
437 * with NumLock off. */
438 retval = NANO_PREVPAGE_KEY;
439 break;
440 case KEY_B2: /* Center (5) on numeric keypad
441 * with NumLock off. */
442 break;
443 case KEY_C1: /* End (1) on numeric keypad
444 * with NumLock off. */
445 retval = NANO_END_KEY;
446 break;
447 case KEY_C3: /* PageDown (4) on numeric
448 * keypad with NumLock off. */
449 retval = NANO_NEXTPAGE_KEY;
450 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000451#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000452 /* Slang doesn't support KEY_BEG. */
453 case KEY_BEG: /* Center (5) on numeric keypad
454 * with NumLock off. */
455 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000456#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000457#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000458 /* HP-UX 10 and 11 don't support KEY_END. */
459 case KEY_END:
460 retval = NANO_END_KEY;
461 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000462#endif
463#ifdef KEY_SUSPEND
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000464 /* Slang doesn't support KEY_SUSPEND. */
465 case KEY_SUSPEND:
466 retval = NANO_SUSPEND_KEY;
467 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000468#endif
469#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000470 /* Slang doesn't support KEY_SLEFT. */
471 case KEY_SLEFT:
472 retval = NANO_BACK_KEY;
473 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000474#endif
475#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000476 /* Slang doesn't support KEY_SRIGHT. */
477 case KEY_SRIGHT:
478 retval = NANO_FORWARD_KEY;
479 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000480#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000481 default:
482 retval = *kbinput;
483 break;
484 }
485 break;
486 case 1:
487 /* One escape followed by a non-escape: escape
488 * sequence mode. Reset the escape counter. If
489 * there aren't any other keys waiting, we have a
490 * meta key sequence, so set meta_key to TRUE and
491 * save the lowercase version of the non-escape
492 * character as the result. If there are other keys
493 * waiting, we have a true escape sequence, so
494 * interpret it. */
495 escapes = 0;
496 if (get_buffer_len() == 0) {
497 *meta_key = TRUE;
498 retval = tolower(*kbinput);
499 } else {
500 int *seq;
501 size_t seq_len;
502 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000503
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000504 /* Put back the non-escape character, get the
505 * complete escape sequence, translate the
506 * sequence into its corresponding key value,
507 * and save that as the result. */
508 unget_input(kbinput, 1);
509 seq_len = get_buffer_len();
510 seq = get_input(NULL, seq_len);
511 retval = get_escape_seq_kbinput(seq, seq_len,
512 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000513
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000514 /* If the escape sequence is unrecognized and
515 * not ignored, put back all of its characters
516 * except for the initial escape. */
517 if (retval == ERR && !ignore_seq)
518 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000519
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000520 free(seq);
521 }
522 break;
523 case 2:
524 /* Two escapes followed by one or more decimal
525 * digits: byte sequence mode. If the word
526 * sequence's range is limited to 2XX (the first
527 * digit is in the '0' to '2' range and it's the
528 * first digit, or it's in the '0' to '9' range and
529 * it's not the first digit), increment the byte
530 * sequence counter and interpret the digit. If the
531 * byte sequence's range is not limited to 2XX, fall
532 * through. */
533 if (('0' <= *kbinput && *kbinput <= '6' &&
534 byte_digits == 0) || ('0' <= *kbinput &&
535 *kbinput <= '9' && byte_digits > 0)) {
536 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000537
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000538 byte_digits++;
539 byte = get_byte_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000540#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000541 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000542#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000543 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000544
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000545 if (byte != ERR) {
546 char *byte_mb = charalloc(mb_cur_max());
547 int byte_mb_len, *seq, i;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000548
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000549 /* If we've read in a complete byte
550 * sequence, reset the byte sequence counter
551 * and the escape counter, and put back the
552 * corresponding byte value. */
553 byte_digits = 0;
554 escapes = 0;
555
556 /* Put back the multibyte equivalent of the
557 * byte value. */
558 byte_mb = make_mbchar(byte, byte_mb,
559 &byte_mb_len);
560
561 seq = (int *)nmalloc(byte_mb_len *
562 sizeof(int));
563
564 for (i = 0; i < byte_mb_len; i++)
565 seq[i] = (unsigned char)byte_mb[i];
566
567 unget_input(seq, byte_mb_len);
568
569 free(seq);
570 free(byte_mb);
571 }
572 } else {
573 /* Reset the escape counter. */
574 escapes = 0;
575 if (byte_digits == 0)
576 /* Two escapes followed by a non-decimal
577 * digit or a decimal digit that would
578 * create a byte sequence greater than 2XX,
579 * and we're not in the middle of a byte
580 * sequence: control character sequence
581 * mode. Interpret the control sequence and
582 * save the corresponding control character
583 * as the result. */
584 retval = get_control_kbinput(*kbinput);
585 else {
586 /* If we're in the middle of a byte
587 * sequence, reset the byte sequence counter
588 * and save the character we got as the
589 * result. */
590 byte_digits = 0;
591 retval = *kbinput;
592 }
593 }
594 break;
595 }
596 }
597
598 /* If we have a result and it's an extended keypad value (i.e, a
599 * value outside of byte range), set func_key to TRUE. */
600 if (retval != ERR)
601 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000602
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000603#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000604 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 +0000605#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000606
607 /* Return the result. */
608 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000609}
610
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000611/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000612 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000613 * are generated when the keypad doesn't support the needed keys. If
614 * the escape sequence is recognized but we want to ignore it, return
615 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
616 * set ignore_seq to FALSE. Assume that Escape has already been read
617 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000618int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000619 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000620{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000621 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000622
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000623 *ignore_seq = FALSE;
624
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000625 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000626 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000627 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000628 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000629 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000630 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000631 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000632 case 'P': /* Esc O 2 P == F13 on
633 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000634 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000635 break;
636 case 'Q': /* Esc O 2 Q == F14 on
637 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000638 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000639 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000640 case 'R': /* Esc O 2 R == F15 on
641 * xterm. */
642 retval = KEY_F(15);
643 break;
644 case 'S': /* Esc O 2 S == F16 on
645 * xterm. */
646 retval = KEY_F(16);
647 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000648 }
649 }
650 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000651 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
652 case 'B': /* Esc O B == Down on
653 * VT100/VT320/xterm. */
654 case 'C': /* Esc O C == Right on
655 * VT100/VT320/xterm. */
656 case 'D': /* Esc O D == Left on
657 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000658 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000659 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000660 case 'E': /* Esc O E == Center (5) on numeric keypad
661 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000662 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000663 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000664 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000665 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000666 break;
667 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000668 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000669 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000670 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000671 * NumLock off on VT100/VT220/VT320/xterm/
672 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000673 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000674 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000675 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000676 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000677 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000678 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000679 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000680 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000681 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000682 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000683 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000684 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000685 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000686 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000687 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000688 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000689 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000690 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000691 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000692 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000693 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000694 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000695 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000696 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000697 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000698 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000699 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000700 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000701 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000702 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000703 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000704 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000705 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000706 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000707 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000708 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000709 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000710 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000711 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000712 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000713 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000714 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000715 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000716 * NumLock off on VT100/VT220/VT320/xterm/
717 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000718 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000719 break;
720 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000721 * NumLock off on VT100/VT220/VT320/xterm/
722 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000723 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000724 break;
725 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000726 * NumLock off on VT100/VT220/VT320/xterm/
727 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000728 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000729 break;
730 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000731 * NumLock off on VT100/VT220/VT320/xterm/
732 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000733 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000734 break;
735 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000736 * with NumLock off on VT100/VT220/VT320/
737 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000738 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000739 break;
740 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000741 * NumLock off on VT100/VT220/VT320/xterm/
742 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000743 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000744 break;
745 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000746 * with NumLock off on VT100/VT220/VT320/
747 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000748 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000749 break;
750 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000751 * with NumLock off on VT100/VT220/VT320/
752 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000753 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000754 break;
755 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000756 * with NumLock off on VT100/VT220/VT320/
757 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000758 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000759 break;
760 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000761 * keypad with NumLock off on VT100/VT220/
762 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000763 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000764 break;
765 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000766 * with NumLock off on VT100/VT220/VT320/
767 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000768 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000769 break;
770 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000771 * with NumLock off on VT100/VT220/VT320/
772 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000773 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000774 break;
775 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000776 * with NumLock off on VT100/VT220/VT320/
777 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000778 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000779 break;
780 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000781 * with NumLock off on VT100/VT220/VT320/
782 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000783 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000784 break;
785 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000786 * with NumLock off on VT100/VT220/VT320/
787 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000788 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000789 break;
790 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000791 * with NumLock off on VT100/VT220/VT320/
792 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000793 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000794 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000795 }
796 break;
797 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000798 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000799 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000800 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000801 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000802 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000803 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000804 break;
805 }
806 break;
807 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000808 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000809 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000810 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000811 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000812 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
813 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000814 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000815 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000816 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
817 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000818 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000819 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000820 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
821 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000822 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000823 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000824 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
825 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000826 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000827 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000828 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
829 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000830 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000831 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000832 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000833 * VT220/VT320/Linux console/
834 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000835 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000836 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000837 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000838 * VT220/VT320/Linux console/
839 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000840 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000841 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000842 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000843 * VT220/VT320/Linux console/
844 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000845 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000846 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000847 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000848 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000849 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000850 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000851 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000852 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000853 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
854 * xterm. */
855 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
856 * xterm. */
857 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
858 * xterm. */
859 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
860 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000861 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000862 break;
863 }
864 }
865 break;
866 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000867 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000868 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000869 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
870 * xterm. */
871 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
872 * xterm. */
873 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
874 * xterm. */
875 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
876 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000877 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000878 break;
879 }
880 }
881 break;
882 }
883 }
884 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000885 default: /* Esc [ 1 ~ == Home on
886 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000887 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000888 break;
889 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000890 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000891 break;
892 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000893 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000894 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000895 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000896 * VT220/VT320/Linux console/
897 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000898 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000899 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000900 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000901 * VT220/VT320/Linux console/
902 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000903 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000904 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000905 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000906 * VT220/VT320/Linux console/
907 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000908 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000909 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000910 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000911 * VT220/VT320/Linux console/
912 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000913 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000914 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000915 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000916 * VT220/VT320/Linux console/
917 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000918 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000919 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000920 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000921 * VT220/VT320/Linux console/
922 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000923 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000924 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000925 case '8': /* Esc [ 2 8 ~ == F15 on
926 * VT220/VT320/Linux console/
927 * rxvt/Eterm. */
928 retval = KEY_F(15);
929 break;
930 case '9': /* Esc [ 2 9 ~ == F16 on
931 * VT220/VT320/Linux console/
932 * rxvt/Eterm. */
933 retval = KEY_F(16);
934 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000935 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000936 * VT220/VT320/Linux console/
937 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000938 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000939 break;
940 }
941 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000942 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000943 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
944 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000945 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000946 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000947 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000948 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000949 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000950 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000951 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
952 * Linux console/xterm; Esc [ 5 ^ ==
953 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000954 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000955 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000956 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
957 * Linux console/xterm; Esc [ 6 ^ ==
958 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000959 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000960 break;
961 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000962 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000963 break;
964 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000965 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000966 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000967 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000968 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000969 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000970 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000971 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000972 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000973 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000974 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000975 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000976 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000977 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000978 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000979 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000980 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000981 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000982 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000983 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000984 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000985 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000986 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000987 case 'E': /* Esc [ E == Center (5) on numeric keypad
988 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000989 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000990 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000991 case 'F': /* Esc [ F == End on FreeBSD
992 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000993 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000994 break;
995 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000996 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000997 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000998 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000999 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001000 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001001 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001002 break;
1003 case 'I': /* Esc [ I == PageUp on FreeBSD
1004 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001005 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001006 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001007 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001008 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001009 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001010 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001011 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001012 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001013 break;
1014 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001015 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001016 break;
1017 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001018 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001019 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001020 case 'P': /* Esc [ O P == F1 on
1021 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001022 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001023 break;
1024 case 'Q': /* Esc [ O Q == F2 on
1025 * xterm. */
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 'R': /* Esc [ O R == F3 on
1029 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001030 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001031 break;
1032 case 'S': /* Esc [ O S == F4 on
1033 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001034 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001035 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001036 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001037 } else {
1038 /* Esc [ O == F3 on FreeBSD console. */
1039 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001040 }
1041 break;
1042 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001043 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001044 break;
1045 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001046 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001047 break;
1048 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001049 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001050 break;
1051 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001052 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001053 break;
1054 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001055 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001056 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001057 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001058 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001059 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001060 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001062 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001063 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001064 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001065 break;
1066 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001067 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001068 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001069 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001070 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001071 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001072 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001073 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001074 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001075 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001076 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001077 case 'c': /* Esc [ c == Shift-Right on rxvt/
1078 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001079 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001080 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001081 break;
1082 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001083 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001084 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001085 case 'A': /* Esc [ [ A == F1 on Linux
1086 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001087 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001088 break;
1089 case 'B': /* Esc [ [ B == F2 on Linux
1090 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001091 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001092 break;
1093 case 'C': /* Esc [ [ C == F3 on Linux
1094 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001095 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001096 break;
1097 case 'D': /* Esc [ [ D == F4 on Linux
1098 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001099 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001100 break;
1101 case 'E': /* Esc [ [ E == F5 on Linux
1102 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001103 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001104 break;
1105 }
1106 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001107 break;
1108 }
1109 break;
1110 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001111 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001112
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001113#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001114 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001115#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001116
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001117 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001118}
1119
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001120/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001121 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001122 * to many escape sequences. */
1123int get_escape_seq_abcd(int kbinput)
1124{
1125 switch (tolower(kbinput)) {
1126 case 'a':
1127 return NANO_PREVLINE_KEY;
1128 case 'b':
1129 return NANO_NEXTLINE_KEY;
1130 case 'c':
1131 return NANO_FORWARD_KEY;
1132 case 'd':
1133 return NANO_BACK_KEY;
1134 default:
1135 return ERR;
1136 }
1137}
1138
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001139/* Translate a byte sequence: turn a three-digit decimal number from
1140 * 000 to 255 into its corresponding byte value. */
1141int get_byte_kbinput(int kbinput
1142#ifndef NANO_SMALL
1143 , bool reset
1144#endif
1145 )
1146{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001147 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001148 int retval = ERR;
1149
1150#ifndef NANO_SMALL
1151 if (reset) {
1152 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001153 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001154 return ERR;
1155 }
1156#endif
1157
1158 /* Increment the byte digit counter. */
1159 byte_digits++;
1160
1161 switch (byte_digits) {
1162 case 1:
1163 /* One digit: reset the byte sequence holder and add the
1164 * digit we got to the 100's position of the byte sequence
1165 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001166 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001167 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001168 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001169 else
1170 /* If the character we got isn't a decimal digit, or if
1171 * it is and it would put the byte sequence out of byte
1172 * range, save it as the result. */
1173 retval = kbinput;
1174 break;
1175 case 2:
1176 /* Two digits: add the digit we got to the 10's position of
1177 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001178 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1179 '6' <= kbinput && kbinput <= '9'))
1180 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001181 else
1182 /* If the character we got isn't a decimal digit, or if
1183 * it is and it would put the byte sequence out of byte
1184 * range, save it as the result. */
1185 retval = kbinput;
1186 break;
1187 case 3:
1188 /* Three digits: add the digit we got to the 1's position of
1189 * the byte sequence holder, and save the corresponding word
1190 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001191 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1192 '6' <= kbinput && kbinput <= '9')) {
1193 byte += (kbinput - '0');
1194 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001195 } else
1196 /* If the character we got isn't a decimal digit, or if
1197 * it is and it would put the word sequence out of word
1198 * range, save it as the result. */
1199 retval = kbinput;
1200 break;
1201 default:
1202 /* More than three digits: save the character we got as the
1203 * result. */
1204 retval = kbinput;
1205 break;
1206 }
1207
1208 /* If we have a result, reset the byte digit counter and the byte
1209 * sequence holder. */
1210 if (retval != ERR) {
1211 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001212 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001213 }
1214
1215#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001216 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 +00001217#endif
1218
1219 return retval;
1220}
1221
1222/* Translate a word sequence: turn a four-digit hexadecimal number from
1223 * 0000 to ffff (case-insensitive) into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001224int get_word_kbinput(int kbinput
1225#ifndef NANO_SMALL
1226 , bool reset
1227#endif
1228 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001229{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001230 static int word_digits = 0, word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001231 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001232
1233#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001234 if (reset) {
1235 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001236 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001237 return ERR;
1238 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001239#endif
1240
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001241 /* Increment the word digit counter. */
1242 word_digits++;
1243
1244 switch (word_digits) {
1245 case 1:
1246 /* One digit: reset the word sequence holder and add the
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001247 * digit we got to the 4096's position of the word sequence
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001248 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001249 word = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001250 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001251 word += (kbinput - '0') * 4096;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001252 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001253 word += (tolower(kbinput) + 10 - 'a') * 4096;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001254 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001255 /* If the character we got isn't a hexadecimal digit, or
1256 * if it is and it would put the word sequence out of
1257 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001258 retval = kbinput;
1259 break;
1260 case 2:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001261 /* Two digits: add the digit we got to the 256's position of
1262 * the word sequence holder. */
1263 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001264 word += (kbinput - '0') * 256;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001265 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001266 word += (tolower(kbinput) + 10 - 'a') * 256;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001267 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001268 /* If the character we got isn't a hexadecimal digit, or
1269 * if it is and it would put the word sequence out of
1270 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001271 retval = kbinput;
1272 break;
1273 case 3:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001274 /* Three digits: add the digit we got to the 16's position
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001275 * of the word sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001276 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001277 word += (kbinput - '0') * 16;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001278 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001279 word += (tolower(kbinput) + 10 - 'a') * 16;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001280 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001281 /* If the character we got isn't a hexadecimal digit, or
1282 * if it is and it would put the word sequence out of
1283 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001284 retval = kbinput;
1285 break;
1286 case 4:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001287 /* Four digits: add the digit we got to the 1's position of
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001288 * the word sequence holder, and save the corresponding word
1289 * value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001290 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001291 word += (kbinput - '0');
1292 retval = word;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001293 } else if ('a' <= tolower(kbinput) &&
1294 tolower(kbinput) <= 'f') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001295 word += (tolower(kbinput) + 10 - 'a');
1296 retval = word;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001297 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001298 /* If the character we got isn't a hexadecimal digit, or
1299 * if it is and it would put the word sequence out of
1300 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001301 retval = kbinput;
1302 break;
1303 default:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001304 /* More than four digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001305 * result. */
1306 retval = kbinput;
1307 break;
1308 }
1309
1310 /* If we have a result, reset the word digit counter and the word
1311 * sequence holder. */
1312 if (retval != ERR) {
1313 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001314 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001315 }
1316
1317#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001318 fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word = %d, retval = %d\n", kbinput, word_digits, word, retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001319#endif
1320
1321 return retval;
1322}
1323
1324/* Translate a control character sequence: turn an ASCII non-control
1325 * character into its corresponding control character. */
1326int get_control_kbinput(int kbinput)
1327{
1328 int retval;
1329
1330 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1331 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1332 kbinput == '`')
1333 retval = NANO_CONTROL_SPACE;
1334 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1335 else if ('3' <= kbinput && kbinput <= '7')
1336 retval = kbinput - 24;
1337 /* Ctrl-8 (Ctrl-?) */
1338 else if (kbinput == '8' || kbinput == '?')
1339 retval = NANO_CONTROL_8;
1340 /* Ctrl-A to Ctrl-_ */
1341 else if ('A' <= kbinput && kbinput <= '_')
1342 retval = kbinput - 64;
1343 /* Ctrl-a to Ctrl-~ */
1344 else if ('a' <= kbinput && kbinput <= '~')
1345 retval = kbinput - 96;
1346 else
1347 retval = kbinput;
1348
1349#ifdef DEBUG
1350 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1351#endif
1352
1353 return retval;
1354}
1355
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001356/* Put the output-formatted characters in output back into the default
1357 * keystroke buffer, so that they can be parsed and displayed as output
1358 * again. */
1359void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001360{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001361 int *input;
1362 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001363
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001364 if (output_len == 0)
1365 return;
1366
1367 input = (int *)nmalloc(output_len * sizeof(int));
1368 for (i = 0; i < output_len; i++)
1369 input[i] = (int)output[i];
1370 unget_input(input, output_len);
1371 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001372}
1373
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001374/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001375 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1376int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1377{
1378 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001379
1380 /* Turn off flow control characters if necessary so that we can type
1381 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001382 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001383 if (ISSET(PRESERVE))
1384 disable_flow_control();
1385 keypad(win, FALSE);
1386
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001387 /* Read in a stream of characters and interpret it if possible. */
1388 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001389
1390 /* Turn flow control characters back on if necessary and turn the
1391 * keypad back on now that we're done. */
1392 if (ISSET(PRESERVE))
1393 enable_flow_control();
1394 keypad(win, TRUE);
1395
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001396 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001397}
1398
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001399/* Read in a stream of all available characters, and return the length
1400 * of the string in kbinput_len. Translate the first few characters of
1401 * the input into the corresponding word value if possible. After that,
1402 * leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001403int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001404{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001405 int *kbinput, word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001406
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001407 /* Read in the first keystroke. */
1408 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001409
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001410 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001411 word = get_word_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001412#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001413 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001414#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001415 );
1416
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001417 /* If the first keystroke isn't a hexadecimal digit, put back the
1418 * first keystroke. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001419 if (word != ERR)
1420 unget_input(kbinput, 1);
1421 /* Otherwise, read in keystrokes until we have a complete word
1422 * sequence, and put back the corresponding word value. */
1423 else {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001424 char *word_mb = charalloc(mb_cur_max());
1425 int word_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001426
1427 while (word == ERR) {
1428 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001429
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001430 word = get_word_kbinput(*kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001431#ifndef NANO_SMALL
1432 , FALSE
1433#endif
1434 );
1435 }
1436
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001437 /* Put back the multibyte equivalent of the word value. */
1438 word_mb = make_mbchar(word, word_mb, &word_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001439
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001440 seq = (int *)nmalloc(word_mb_len * sizeof(int));
1441
1442 for (i = 0; i < word_mb_len; i++)
1443 seq[i] = (unsigned char)word_mb[i];
1444
1445 unget_input(seq, word_mb_len);
1446
1447 free(seq);
1448 free(word_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001449 }
1450
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001451 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001452 * result. */
1453 *kbinput_len = get_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001454 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001455
1456 return retval;
1457}
1458
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001459#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001460/* Check for a mouse event, and if one's taken place, save the
1461 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001462 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1463 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001464 * place on it, figure out which shortcut was clicked and put back the
1465 * equivalent keystroke(s). Return FALSE if no keystrokes were
1466 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001467 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001468bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001469{
1470 MEVENT mevent;
1471
1472 *mouse_x = -1;
1473 *mouse_y = -1;
1474
1475 /* First, get the actual mouse event. */
1476 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001477 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001478
1479 /* Save the screen coordinates where the mouse event took place. */
1480 *mouse_x = mevent.x;
1481 *mouse_y = mevent.y;
1482
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001483 /* If we're allowing shortcuts, the current shortcut list is being
1484 * displayed on the last two lines of the screen, and the mouse
1485 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001486 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001487 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1488 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001489 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001490 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001491 /* The number of shortcuts in the current shortcut list. */
1492 const shortcut *s = currshortcut;
1493 /* The actual shortcut we clicked on, starting at the first
1494 * one in the current shortcut list. */
1495
1496 /* Get the shortcut lists' length. */
1497 if (currshortcut == main_list)
1498 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001499 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001500 currslen = length_of_list(currshortcut);
1501
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001502 /* We don't show any more shortcuts than the main list
1503 * does. */
1504 if (currslen > MAIN_VISIBLE)
1505 currslen = MAIN_VISIBLE;
1506 }
1507
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001508 /* Calculate the width of each shortcut in the list (it's the
1509 * same for all of them). */
1510 if (currslen < 2)
1511 i = COLS / 6;
1512 else
1513 i = COLS / ((currslen / 2) + (currslen % 2));
1514
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001515 /* Calculate the y-coordinate relative to the beginning of
1516 * bottomwin. */
1517 j = *mouse_y - ((2 - no_more_space()) + 1) - editwinrows;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001518
1519 /* If we're on the statusbar, beyond the end of the shortcut
1520 * list, or beyond the end of a shortcut on the right side of
1521 * the screen, don't do anything. */
1522 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001523 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001524 j = (*mouse_x / i) * 2 + j;
1525 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001526 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001527
1528 /* Go through the shortcut list to determine which shortcut was
1529 * clicked. */
1530 for (; j > 0; j--)
1531 s = s->next;
1532
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001533 /* And put back the equivalent key. Assume that each shortcut
1534 * has, at the very least, an equivalent control key, an
1535 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001536 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001537 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001538 return TRUE;
1539 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001540 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001541 return TRUE;
1542 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001543 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001544 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001545}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001546#endif /* !DISABLE_MOUSE */
1547
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001548const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001549 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001550{
1551 const shortcut *s = s_list;
1552 size_t slen = length_of_list(s_list);
1553
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001554#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001555 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 +00001556#endif
1557
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001558 /* Check for shortcuts. */
1559 for (; slen > 0; slen--) {
1560 /* We've found a shortcut if:
1561 *
1562 * 1. The key exists.
1563 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001564 * 3. meta_key is TRUE and the key is the primary or
1565 * miscellaneous meta sequence in the shortcut list.
1566 * 4. func_key is TRUE and the key is a function key in the
1567 * shortcut list. */
1568
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001569 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1570 (*meta_key == TRUE && (*kbinput == s->metaval ||
1571 *kbinput == s->miscval)) || (*func_key == TRUE &&
1572 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001573 break;
1574 }
1575
1576 s = s->next;
1577 }
1578
1579 /* Translate the shortcut to either its control key or its meta key
1580 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001581 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001582 if (slen > 0) {
1583 if (s->ctrlval != NANO_NO_KEY) {
1584 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001585 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001586 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001587 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001588 } else if (s->metaval != NANO_NO_KEY) {
1589 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001590 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001591 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001592 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001593 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001594 }
1595
1596 return NULL;
1597}
1598
1599#ifndef NANO_SMALL
1600const toggle *get_toggle(int kbinput, bool meta_key)
1601{
1602 const toggle *t = toggles;
1603
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001604#ifdef DEBUG
1605 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1606#endif
1607
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001608 /* Check for toggles. */
1609 for (; t != NULL; t = t->next) {
1610 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001611 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001612 if (meta_key && kbinput == t->val)
1613 break;
1614 }
1615
1616 return t;
1617}
1618#endif /* !NANO_SMALL */
1619
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001620int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001621 bool *ran_func, bool *finished, bool allow_funcs)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001622{
1623 int input;
1624 /* The character we read in. */
1625 static int *kbinput = NULL;
1626 /* The input buffer. */
1627 static size_t kbinput_len = 0;
1628 /* The length of the input buffer. */
1629 const shortcut *s;
1630 bool have_shortcut;
1631
1632 *s_or_t = FALSE;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001633 *ran_func = FALSE;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001634 *finished = FALSE;
1635
1636 /* Read in a character. */
1637 input = get_kbinput(bottomwin, meta_key, func_key);
1638
1639#ifndef DISABLE_MOUSE
1640 /* If we got a mouse click and it was on a shortcut, read in the
1641 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001642 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001643 if (do_mouse())
1644 input = get_kbinput(bottomwin, meta_key, func_key);
1645 else
1646 input = ERR;
1647 }
1648#endif
1649
1650 /* Check for a shortcut in the current list. */
1651 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1652
1653 /* If we got a shortcut from the current list, or a "universal"
1654 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1655 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1656 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1657 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1658 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001659 input == NANO_CUT_KEY ||
1660#ifndef NANO_SMALL
1661 input == NANO_NEXTWORD_KEY ||
1662#endif
1663 (*meta_key == TRUE && (
1664#ifndef NANO_SMALL
1665 input == NANO_PREVWORD_KEY ||
1666#endif
1667 input == NANO_VERBATIM_KEY)));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001668
1669 /* Set s_or_t to TRUE if we got a shortcut. */
1670 *s_or_t = have_shortcut;
1671
1672 if (allow_funcs) {
1673 if (input != ERR && *s_or_t == FALSE && !is_cntrl_char(input)) {
1674 /* If we're using restricted mode, the filename isn't blank,
1675 * and we're at the "Write File" prompt, disable text
1676 * input. */
1677 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1678 currshortcut != writefile_list) {
1679 kbinput_len++;
1680 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1681 sizeof(int));
1682 kbinput[kbinput_len - 1] = input;
1683 }
1684 }
1685
1686 /* If we got a shortcut, or if there aren't any other characters
1687 * waiting after the one we read in, we need to display all the
1688 * characters in the input buffer if it isn't empty. */
1689 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1690 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001691
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001692 /* Display all the characters in the input buffer at
1693 * once. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001694 char *output = charalloc(kbinput_len + 1);
1695 size_t i;
1696 bool got_enter;
1697 /* Whether we got the Enter key. */
1698
1699 for (i = 0; i < kbinput_len; i++)
1700 output[i] = (char)kbinput[i];
1701 output[i] = '\0';
1702
1703 do_statusbar_output(output, kbinput_len, &got_enter);
1704
1705 free(output);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001706
1707 /* Empty the input buffer. */
1708 kbinput_len = 0;
1709 free(kbinput);
1710 kbinput = NULL;
1711 }
1712 }
1713
1714 if (have_shortcut) {
1715 switch (input) {
1716 /* Handle the "universal" statusbar prompt shortcuts. */
1717 case NANO_REFRESH_KEY:
1718 total_refresh();
1719 break;
1720 case NANO_HOME_KEY:
1721 do_statusbar_home();
1722 break;
1723 case NANO_END_KEY:
1724 do_statusbar_end();
1725 break;
1726 case NANO_FORWARD_KEY:
1727 do_statusbar_right();
1728 break;
1729 case NANO_BACK_KEY:
1730 do_statusbar_left();
1731 break;
1732 case NANO_BACKSPACE_KEY:
1733 /* If we're using restricted mode, the filename
1734 * isn't blank, and we're at the "Write File"
1735 * prompt, disable Backspace. */
1736 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1737 currshortcut != writefile_list)
1738 do_statusbar_backspace();
1739 break;
1740 case NANO_DELETE_KEY:
1741 /* If we're using restricted mode, the filename
1742 * isn't blank, and we're at the "Write File"
1743 * prompt, disable Delete. */
1744 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1745 currshortcut != writefile_list)
1746 do_statusbar_delete();
1747 break;
1748 case NANO_CUT_KEY:
1749 /* If we're using restricted mode, the filename
1750 * isn't blank, and we're at the "Write File"
1751 * prompt, disable Cut. */
1752 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1753 currshortcut != writefile_list)
1754 do_statusbar_cut_text();
1755 break;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001756#ifndef NANO_SMALL
1757 case NANO_NEXTWORD_KEY:
1758 do_statusbar_next_word();
1759 break;
1760 case NANO_PREVWORD_KEY:
1761 if (*meta_key == TRUE)
1762 do_statusbar_prev_word();
1763 break;
1764#endif
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001765 case NANO_VERBATIM_KEY:
1766 if (*meta_key == TRUE) {
1767 /* If we're using restricted mode, the filename
1768 * isn't blank, and we're at the "Write File"
1769 * prompt, disable verbatim input. */
1770 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001771 currshortcut != writefile_list) {
1772 bool got_enter;
1773 /* Whether we got the Enter key. */
1774
1775 do_statusbar_verbatim_input(&got_enter);
1776
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001777 /* If we got the Enter key, set input to the
1778 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001779 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001780 if (got_enter) {
1781 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001782 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001783 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001784 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001785 break;
1786 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001787 /* Handle the normal statusbar prompt shortcuts, setting
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001788 * ran_func to TRUE if we try to run their associated
1789 * functions and setting finished to TRUE to indicate
1790 * that we're done after trying to run their associated
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001791 * functions. */
1792 default:
1793 if (s->func != NULL) {
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001794 *ran_func = TRUE;
1795 if (!ISSET(VIEW_MODE) || s->viewok)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001796 s->func();
1797 }
1798 *finished = TRUE;
1799 }
1800 }
1801 }
1802
1803 return input;
1804}
1805
1806#ifndef DISABLE_MOUSE
1807bool do_statusbar_mouse(void)
1808{
1809 /* FIXME: If we clicked on a location in the statusbar, the cursor
1810 * should move to the location we clicked on. This functionality
1811 * should be in this function. */
1812 int mouse_x, mouse_y;
1813 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1814}
1815#endif
1816
1817void do_statusbar_home(void)
1818{
1819#ifndef NANO_SMALL
1820 if (ISSET(SMART_HOME)) {
1821 size_t statusbar_x_save = statusbar_x;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001822 char *blank_mb = charalloc(mb_cur_max());
David Lawrence Ramsey7801d7b2005-01-14 21:59:01 +00001823 int blank_mb_len;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001824
1825 statusbar_x = 0;
1826
1827 while (statusbar_x < statusbar_xend) {
David Lawrence Ramsey7801d7b2005-01-14 21:59:01 +00001828 blank_mb_len = parse_mbchar(answer + statusbar_x,
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001829 blank_mb
1830#ifdef NANO_WIDE
1831 , NULL
1832#endif
1833 , NULL);
1834
1835 if (!is_blank_mbchar(blank_mb))
1836 break;
1837
David Lawrence Ramsey7801d7b2005-01-14 21:59:01 +00001838 statusbar_x += blank_mb_len;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001839 }
1840
1841 free(blank_mb);
1842
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001843 if (statusbar_x == statusbar_x_save ||
1844 statusbar_x == statusbar_xend)
1845 statusbar_x = 0;
1846 } else
1847#endif
1848 statusbar_x = 0;
1849}
1850
1851void do_statusbar_end(void)
1852{
1853 statusbar_x = statusbar_xend;
1854}
1855
1856void do_statusbar_right(void)
1857{
1858 if (statusbar_x < statusbar_xend)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001859 statusbar_x = move_mbright(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001860}
1861
1862void do_statusbar_left(void)
1863{
1864 if (statusbar_x > 0)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001865 statusbar_x = move_mbleft(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001866}
1867
1868void do_statusbar_backspace(void)
1869{
1870 if (statusbar_x > 0) {
1871 do_statusbar_left();
1872 do_statusbar_delete();
1873 }
1874}
1875
1876void do_statusbar_delete(void)
1877{
1878 if (statusbar_x < statusbar_xend) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001879 int char_buf_len = parse_mbchar(answer + statusbar_x, NULL
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001880#ifdef NANO_WIDE
1881 , NULL
1882#endif
David Lawrence Ramseyd96851f2005-01-07 22:39:43 +00001883 , NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001884
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001885 charmove(answer + statusbar_x, answer + statusbar_x +
1886 char_buf_len, statusbar_xend - statusbar_x -
1887 char_buf_len + 1);
1888 statusbar_xend -= char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001889 }
1890}
1891
1892void do_statusbar_cut_text(void)
1893{
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001894 if (ISSET(CUT_TO_END)) {
1895 null_at(&answer, statusbar_x);
1896 statusbar_xend = statusbar_x;
1897 } else {
1898 null_at(&answer, 0);
1899 statusbar_x = 0;
1900 statusbar_xend = 0;
1901 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001902}
1903
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001904#ifndef NANO_SMALL
1905void do_statusbar_next_word(void)
1906{
1907 char *char_mb = charalloc(mb_cur_max());
1908 int char_mb_len;
1909
1910 assert(answer != NULL);
1911
1912 /* Move forward until we find the character after the last letter of
1913 * the current word. */
1914 while (statusbar_x < statusbar_xend) {
1915 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb
1916#ifdef NANO_WIDE
1917 , NULL
1918#endif
1919 , NULL);
1920
1921 /* If we've found it, stop moving forward through the current
1922 * line. */
1923 if (!is_alnum_mbchar(char_mb))
1924 break;
1925
1926 statusbar_x += char_mb_len;
1927 }
1928
1929 /* Move forward until we find the first letter of the next word. */
1930 if (statusbar_x < statusbar_xend)
1931 current_x += char_mb_len;
1932
1933 while (statusbar_x < statusbar_xend) {
1934 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb
1935#ifdef NANO_WIDE
1936 , NULL
1937#endif
1938 , NULL);
1939
1940 /* If we've found it, stop moving forward through the current
1941 * line. */
1942 if (is_alnum_mbchar(char_mb))
1943 break;
1944
1945 statusbar_x += char_mb_len;
1946 }
1947
1948 free(char_mb);
1949}
1950
1951void do_statusbar_prev_word(void)
1952{
1953 char *char_mb = charalloc(mb_cur_max());
1954 int char_mb_len;
1955 bool begin_line = FALSE;
1956
1957 assert(answer != NULL);
1958
1959 /* Move backward until we find the character before the first letter
1960 * of the current word. */
1961 while (!begin_line) {
1962 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb
1963#ifdef NANO_WIDE
1964 , NULL
1965#endif
1966 , NULL);
1967
1968 /* If we've found it, stop moving backward through the current
1969 * line. */
1970 if (!is_alnum_mbchar(char_mb))
1971 break;
1972
1973 if (statusbar_x == 0)
1974 begin_line = TRUE;
1975 else
1976 statusbar_x = move_mbleft(answer, statusbar_x);
1977 }
1978
1979 /* Move backward until we find the last letter of the previous
1980 * word. */
1981 if (statusbar_x == 0)
1982 begin_line = TRUE;
1983 else
1984 statusbar_x = move_mbleft(answer, statusbar_x);
1985
1986 while (!begin_line) {
1987 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb
1988#ifdef NANO_WIDE
1989 , NULL
1990#endif
1991 , NULL);
1992
1993 /* If we've found it, stop moving backward through the current
1994 * line. */
1995 if (is_alnum_mbchar(char_mb))
1996 break;
1997
1998 if (statusbar_x == 0)
1999 begin_line = TRUE;
2000 else
2001 statusbar_x = move_mbleft(answer, statusbar_x);
2002 }
2003
2004 /* If we've found it, move backward until we find the character
2005 * before the first letter of the previous word. */
2006 if (!begin_line) {
2007 if (statusbar_x == 0)
2008 begin_line = TRUE;
2009 else
2010 statusbar_x = move_mbleft(answer, statusbar_x);
2011
2012 while (!begin_line) {
2013 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb
2014#ifdef NANO_WIDE
2015 , NULL
2016#endif
2017 , NULL);
2018
2019 /* If we've found it, stop moving backward through the
2020 * current line. */
2021 if (!is_alnum_mbchar(char_mb))
2022 break;
2023
2024 if (statusbar_x == 0)
2025 begin_line = TRUE;
2026 else
2027 statusbar_x = move_mbleft(answer, statusbar_x);
2028 }
2029
2030 /* If we've found it, move forward to the first letter of the
2031 * previous word. */
2032 if (!begin_line)
2033 statusbar_x += char_mb_len;
2034 }
2035
2036 free(char_mb);
2037}
2038#endif
2039
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002040void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002041{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002042 int *kbinput;
2043 size_t kbinput_len, i;
2044 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002045
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002046 *got_enter = FALSE;
2047
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002048 /* Read in all the verbatim characters. */
2049 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
2050
2051 /* Display all the verbatim characters at once. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002052 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002053
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002054 for (i = 0; i < kbinput_len; i++)
2055 output[i] = (char)kbinput[i];
2056 output[i] = '\0';
2057
2058 do_statusbar_output(output, kbinput_len, got_enter);
2059
2060 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002061}
2062
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002063void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002064 *got_enter)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002065{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002066 size_t i = 0;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002067
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002068 char *char_buf = charalloc(mb_cur_max());
2069 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002070
2071 assert(answer != NULL);
2072
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002073 *got_enter = FALSE;
2074
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002075 while (i < output_len) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002076 /* Null to newline, if needed. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002077 if (output[i] == '\0')
2078 output[i] = '\n';
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002079 /* Newline to Enter, if needed. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002080 else if (output[i] == '\n') {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002081 /* Set got_enter to TRUE to indicate that we got the Enter
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002082 * key, put back the rest of the characters in output so
2083 * that they can be parsed and output again, and get out. */
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002084 *got_enter = TRUE;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002085 unparse_kbinput(output + i, output_len - i);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002086 return;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002087 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002088
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002089 /* Interpret the next multibyte character. If it's an invalid
2090 * multibyte character, interpret it as though it's a byte
2091 * character. */
2092 char_buf_len = parse_mbchar(output + i, char_buf
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002093#ifdef NANO_WIDE
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002094 , NULL
2095#endif
2096 , NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002097
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002098 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002099
2100 /* More dangerousness fun =) */
David Lawrence Ramsey49ff08b2005-01-14 04:13:45 +00002101 answer = charealloc(answer, statusbar_xend +
2102 (char_buf_len * 2));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002103
2104 assert(statusbar_x <= statusbar_xend);
2105
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002106 charmove(&answer[statusbar_x + char_buf_len],
2107 &answer[statusbar_x], statusbar_xend - statusbar_x +
2108 char_buf_len);
2109 charcpy(&answer[statusbar_x], char_buf, char_buf_len);
2110 statusbar_xend += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002111
2112 do_statusbar_right();
2113 }
2114
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002115 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002116}
2117
Chris Allegretta6df90f52002-07-19 01:08:59 +00002118/* Return the placewewant associated with current_x. That is, xplustabs
2119 * is the zero-based column position of the cursor. Value is no smaller
2120 * than current_x. */
2121size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002122{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002123 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002124}
2125
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002126/* actual_x() gives the index in str of the character displayed at
2127 * column xplus. That is, actual_x() is the largest value such that
2128 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2129size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002130{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002131 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002132 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002133 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002134 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002135
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002136 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002137
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002138 while (*str != '\0') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002139 int str_len = parse_mbchar(str, NULL
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002140#ifdef NANO_WIDE
2141 , NULL
2142#endif
David Lawrence Ramseyd96851f2005-01-07 22:39:43 +00002143 , &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002144
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002145 if (length > xplus)
2146 break;
2147
2148 i += str_len;
2149 str += str_len;
2150 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002151
Chris Allegretta6df90f52002-07-19 01:08:59 +00002152 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002153}
2154
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002155/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002156 * columns wide are the first size characters of str? */
2157size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002158{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002159 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002160 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002161
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002162 if (size == 0)
2163 return 0;
2164
2165 assert(str != NULL);
2166
2167 while (*str != '\0') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002168 int str_len = parse_mbchar(str, NULL
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002169#ifdef NANO_WIDE
2170 , NULL
2171#endif
David Lawrence Ramseyd96851f2005-01-07 22:39:43 +00002172 , &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002173
2174 str += str_len;
2175
2176 if (size <= str_len)
2177 break;
2178
2179 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002180 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002181
Chris Allegretta6df90f52002-07-19 01:08:59 +00002182 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002183}
2184
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002185/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002186size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002187{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002188 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002189}
2190
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002191void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002192{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002193 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002194}
2195
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002196void blank_topbar(void)
2197{
2198 if (!ISSET(MORE_SPACE))
2199 mvwaddstr(topwin, 1, 0, hblank);
2200}
2201
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002202void blank_edit(void)
2203{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002204 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002205 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002206 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002207}
2208
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002209void blank_statusbar(void)
2210{
2211 mvwaddstr(bottomwin, 0, 0, hblank);
2212}
2213
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002214void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002215{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002216 if (statusblank > 1)
2217 statusblank--;
2218 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
2219 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002220 blank_statusbar();
2221 wnoutrefresh(bottomwin);
2222 reset_cursor();
2223 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002224 }
2225}
2226
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002227void blank_bottombars(void)
2228{
2229 if (!ISSET(NO_HELP)) {
2230 mvwaddstr(bottomwin, 1, 0, hblank);
2231 mvwaddstr(bottomwin, 2, 0, hblank);
2232 }
2233}
2234
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002235/* Convert buf into a string that can be displayed on screen. The
2236 * caller wants to display buf starting with column start_col, and
2237 * extending for at most len columns. start_col is zero-based. len is
2238 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002239 * string is dynamically allocated, and should be freed. If dollars is
2240 * TRUE, the caller might put "$" at the beginning or end of the line if
2241 * it's too long. */
2242char *display_string(const char *buf, size_t start_col, size_t len, bool
2243 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002244{
2245 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002246 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002247 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002248 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002249 size_t alloc_len;
2250 /* The length of memory allocated for converted. */
2251 char *converted;
2252 /* The string we return. */
2253 size_t index;
2254 /* Current position in converted. */
2255
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002256 char *buf_mb = charalloc(mb_cur_max());
2257 int buf_mb_len;
2258#ifdef NANO_WIDE
2259 bool bad_char;
2260#endif
2261
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002262 /* If dollars is TRUE, make room for the "$" at the end of the
2263 * line. */
2264 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2265 len--;
2266
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002267 if (len == 0)
2268 return mallocstrcpy(NULL, "");
2269
2270 start_index = actual_x(buf, start_col);
2271 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002272
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002273 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002274
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002275 /* Allocate enough space for the entire line. It should contain
2276 * (len + 2) multibyte characters at most. */
2277 alloc_len = mb_cur_max() * (len + 2);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002278
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002279 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002280 index = 0;
2281
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002282 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002283 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002284 /* We don't display all of buf[start_index] since it starts to
2285 * the left of the screen. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002286 buf_mb_len = parse_mbchar(buf + start_index, buf_mb
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002287#ifdef NANO_WIDE
2288 , NULL
2289#endif
David Lawrence Ramseyd96851f2005-01-07 22:39:43 +00002290 , NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002291
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002292 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002293 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002294 char *ctrl_buf_mb = charalloc(mb_cur_max());
2295 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002296
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002297 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2298 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002299
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002300 for (i = 0; i < ctrl_buf_mb_len; i++)
2301 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002302
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002303 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002304
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002305 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002306
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002307 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002308 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002309 }
2310#ifdef NANO_WIDE
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002311 else if (mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002312 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002313 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002314
2315 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002316 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002317#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002318 }
2319
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002320 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002321 buf_mb_len = parse_mbchar(buf + start_index, buf_mb
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002322#ifdef NANO_WIDE
2323 , &bad_char
2324#endif
David Lawrence Ramseyd96851f2005-01-07 22:39:43 +00002325 , NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002326
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002327 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002328 converted[index++] =
2329#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2330 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
2331#endif
2332 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002333 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002334 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002335 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002336 start_col++;
2337 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002338 /* If buf contains a control character, interpret it. If it
2339 * contains an invalid multibyte control character, interpret
2340 * that character as though it's a normal control character. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002341 } else if (is_cntrl_mbchar(buf_mb)) {
2342 char *ctrl_buf_mb = charalloc(mb_cur_max());
2343 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002344
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002345 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002346 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002347
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002348 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2349 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002350
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002351 for (i = 0; i < ctrl_buf_mb_len; i++)
2352 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002353
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002354 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002355
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002356 free(ctrl_buf_mb);
2357 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002358 converted[index++] =
2359#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2360 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
2361#endif
2362 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002363 start_col++;
2364 } else {
2365 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002366
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002367#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002368 /* If buf contains an invalid multibyte non-control
2369 * character, interpret that character as though it's a
2370 * normal non-control character. */
2371 if (!ISSET(NO_UTF8) && bad_char) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002372 char *bad_buf_mb = charalloc(mb_cur_max());
2373 int bad_buf_mb_len;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002374
David Lawrence Ramsey4c6956b2005-01-12 04:32:43 +00002375 bad_buf_mb = make_mbchar((unsigned char)*buf_mb,
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002376 bad_buf_mb, &bad_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002377
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002378 for (i = 0; i < bad_buf_mb_len; i++)
2379 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002380
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002381 start_col += mbwidth(bad_buf_mb);
2382
2383 free(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002384 } else {
2385#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002386 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002387 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002388
2389 start_col += mbwidth(buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002390#ifdef NANO_WIDE
2391 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002392#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002393 }
2394
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002395 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002396 }
2397
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002398 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002399 converted[index] = '\0';
2400
2401 /* Make sure converted takes up no more than len columns. */
2402 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002403 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002404
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002405 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002406}
2407
Chris Allegretta7662c862003-01-13 01:35:15 +00002408/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002409 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002410 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002411 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002412 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002413void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002414{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002415 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002416 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002417
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002418 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002419
Chris Allegrettab3655b42001-10-22 03:15:31 +00002420 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002421 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002422
Chris Allegretta6df90f52002-07-19 01:08:59 +00002423 mvwaddstr(bottomwin, 0, 0, buf);
2424 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002425
2426 if (COLS > 1)
2427 waddch(bottomwin, x_real < wid ? ' ' : '$');
2428 if (COLS > 2) {
2429 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002430 char *expanded = display_string(inputbuf, page_start, wid,
2431 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002432
2433 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002434 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002435
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002436 waddstr(bottomwin, expanded);
2437 free(expanded);
2438 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2439 } else
2440 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002441 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002442}
2443
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002444/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002445 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002446int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002447#ifndef NANO_SMALL
2448 historyheadtype *history_list,
2449#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002450 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002451#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002452 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002453#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002454 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002455{
2456 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002457 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002458 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002459 /* used by input_tab() */
Chris Allegretta598106e2002-01-19 01:59:37 +00002460
Chris Allegretta5beed502003-01-05 20:41:21 +00002461#ifndef NANO_SMALL
2462 /* for history */
2463 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00002464 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00002465 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002466 int last_kbinput = 0;
2467
2468 /* This variable is used in the search history code. use_cb == 0
2469 means that we're using the existing history and ignoring
2470 currentbuf. use_cb == 1 means that the entry in answer should be
2471 moved to currentbuf or restored from currentbuf to answer.
2472 use_cb == 2 means that the entry in currentbuf should be moved to
2473 answer or restored from answer to currentbuf. */
2474 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002475#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002476 statusbar_xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002477
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002478 /* Only put statusbar_x at the end of the string if it's
2479 * uninitialized, if it would be past the end of the string as it
2480 * is, or if resetstatuspos is TRUE. Otherwise, leave it alone.
2481 * This is so the cursor position stays at the same place if a
2482 * prompt-changing toggle is pressed. */
2483 if (statusbar_x == (size_t)-1 || statusbar_x > statusbar_xend ||
2484 resetstatuspos)
2485 statusbar_x = statusbar_xend;
Chris Allegretta09fc4302003-01-16 22:16:38 +00002486
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002487 answer = charealloc(answer, statusbar_xend + 1);
2488 if (statusbar_xend > 0)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002489 strcpy(answer, def);
2490 else
2491 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002492
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002493 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002494
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002495 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00002496
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002497 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002498
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002499 /* Refresh the edit window before getting input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002500 wnoutrefresh(edit);
2501 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002502
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002503 /* If we're using restricted mode, we aren't allowed to change the
2504 * name of a file once it has one because that would allow writing
2505 * to files not specified on the command line. In this case,
2506 * disable all keys that would change the text if the filename isn't
2507 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002508 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002509 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002510 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002511
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002512 /* If we have a shortcut with an associated function, break out
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002513 * if we're finished after running or trying to run the
2514 * function. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002515 if (finished)
2516 break;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002517
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002518 assert(statusbar_x <= statusbar_xend &&
2519 statusbar_xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002520
Chris Allegretta04d848e2000-11-05 17:54:41 +00002521 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002522 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00002523
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002524 switch (kbinput) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002525 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002526#ifndef NANO_SMALL
2527 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00002528 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002529 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002530 history_list->current = (historytype *)history_list;
2531 history_list->len = strlen(answer);
2532 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002533
Chris Allegretta7662c862003-01-13 01:35:15 +00002534 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002535 complete = get_history_completion(history_list, answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002536 statusbar_x = strlen(complete);
2537 statusbar_xend = statusbar_x;
Chris Allegretta5beed502003-01-05 20:41:21 +00002538 answer = mallocstrcpy(answer, complete);
2539 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002540 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002541#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002542 else
2543#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002544#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002545#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002546 if (allow_tabs) {
Chris Allegretta327abda2003-01-17 05:04:17 +00002547 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002548
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002549 answer = input_tab(answer, statusbar_x, &tabbed, &shift,
2550 list);
2551 statusbar_xend = strlen(answer);
2552 statusbar_x += shift;
2553 if (statusbar_x > statusbar_xend)
2554 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002555 }
2556#endif
2557 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002558 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002559#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002560 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002561
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002562 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2563 isn't NULL, and currentbuf is different from answer,
2564 it means that we're scrolling up at the top of the
2565 search history, and we need to save the current
2566 answer in currentbuf; do this and reset use_cb to
2567 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002568 if (currentbuf == NULL || (use_cb == 1 &&
2569 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002570 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002571 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002572 }
2573
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002574 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2575 is different from answer, it means that we're
2576 scrolling up at the bottom of the search history, and
2577 we need to make the string in currentbuf the current
2578 answer; do this, blow away currentbuf since we don't
2579 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002580 if (currentbuf != NULL && use_cb == 2 &&
2581 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002582 answer = mallocstrcpy(answer, currentbuf);
2583 free(currentbuf);
2584 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002585 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002586 use_cb = 0;
2587
2588 /* else get older search from the history list and save
2589 it in answer; if there is no older search, blank out
2590 answer */
2591 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002592 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002593 statusbar_xend = strlen(history);
Chris Allegretta5beed502003-01-05 20:41:21 +00002594 } else {
2595 answer = mallocstrcpy(answer, "");
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002596 statusbar_xend = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002597 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002598 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002599 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002600#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002601 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002602 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002603#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002604 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002605
2606 /* get newer search from the history list and save it
2607 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002608 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002609 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002610 statusbar_xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002611
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002612 /* if there is no newer search, we're here */
2613
2614 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2615 that we're scrolling down at the bottom of the search
2616 history and we need to make the string in currentbuf
2617 the current answer; do this, blow away currentbuf
2618 since we don't need it anymore, and set use_cb to
2619 1 */
2620 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002621 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002622 free(currentbuf);
2623 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002624 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002625 use_cb = 1;
2626
2627 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2628 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002629 the search history and the current answer (if it's
2630 not blank) needs to be saved in currentbuf; do this,
2631 blank out answer (if necessary), and set use_cb to
2632 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002633 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002634 if (answer[0] != '\0') {
2635 currentbuf = mallocstrcpy(currentbuf, answer);
2636 answer = mallocstrcpy(answer, "");
2637 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002638 statusbar_xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002639 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002640 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002641 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002642 }
2643#endif
2644 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002645 }
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002646#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002647 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002648#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002649 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002650 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002651 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002652
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002653 /* We finished putting in an answer or ran a normal shortcut's
2654 * associated function, so reset statusbar_x. */
2655 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
2656 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002657 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002658
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002659 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002660}
2661
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002662/* Ask a question on the statusbar. Answer will be stored in answer
2663 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2664 * otherwise, the valid shortcut key caught. def is any editable text
2665 * we want to put up by default.
2666 *
2667 * New arg tabs tells whether or not to allow tab completion. */
2668int statusq(bool allow_tabs, const shortcut *s, const char *def,
2669#ifndef NANO_SMALL
2670 historyheadtype *which_history,
2671#endif
2672 const char *msg, ...)
2673{
2674 va_list ap;
2675 char *foo = charalloc(COLS - 3);
2676 int ret;
2677#ifndef DISABLE_TABCOMP
2678 bool list = FALSE;
2679#endif
2680
2681 bottombars(s);
2682
2683 va_start(ap, msg);
2684 vsnprintf(foo, COLS - 4, msg, ap);
2685 va_end(ap);
2686 foo[COLS - 4] = '\0';
2687
2688 ret = nanogetstr(allow_tabs, foo, def,
2689#ifndef NANO_SMALL
2690 which_history,
2691#endif
2692 s
2693#ifndef DISABLE_TABCOMP
2694 , &list
2695#endif
2696 );
2697 free(foo);
2698 resetstatuspos = FALSE;
2699
2700 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002701 case NANO_CANCEL_KEY:
2702 ret = -1;
2703 resetstatuspos = TRUE;
2704 break;
2705 case NANO_ENTER_KEY:
2706 ret = (answer[0] == '\0') ? -2 : 0;
2707 resetstatuspos = TRUE;
2708 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002709 }
2710 blank_statusbar();
2711
2712#ifdef DEBUG
2713 fprintf(stderr, "I got \"%s\"\n", answer);
2714#endif
2715
2716#ifndef DISABLE_TABCOMP
2717 /* if we've done tab completion, there might be a list of
2718 filename matches on the edit window at this point; make sure
2719 they're cleared off. */
2720 if (list)
2721 edit_refresh();
2722#endif
2723
2724 return ret;
2725}
2726
2727void statusq_abort(void)
2728{
2729 resetstatuspos = TRUE;
2730}
2731
Chris Allegrettaf717f982003-02-13 22:25:01 +00002732void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002733{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002734 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002735 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002736 size_t verlen = strlenpt(VERMSG) + 1;
2737 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002738 const char *prefix;
2739 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2740 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002741 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002742 const char *state;
2743 /* "Modified", "View", or spaces the length of "Modified".
2744 * Tells the state of this buffer. */
2745 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002746 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002747 char *exppath = NULL;
2748 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002749 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002750 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002751 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002752 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002753
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002754 assert(path != NULL || filename != NULL);
2755 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002756
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002757 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002758
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002759 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002760
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002761 if (COLS <= 5 || COLS - 5 < verlen)
2762 space = 0;
2763 else {
2764 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002765 /* Reserve 2/3 of the screen plus one column for after the
2766 * version message. */
2767 if (space < COLS - (COLS / 3) + 1)
2768 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002769 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002770
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002771 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002772 /* The version message should only take up 1/3 of the screen
2773 * minus one column. */
2774 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002775 waddstr(topwin, " ");
2776 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002777
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002778 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002779 state = _("Modified");
2780 else if (path == NULL && ISSET(VIEW_MODE))
2781 state = _("View");
2782 else {
2783 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002784 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002785 state = &hblank[COLS - statelen];
2786 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002787 statelen = strnlenpt(state, COLS);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002788 /* We need a space before state. */
2789 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2790 statelen++;
2791
2792 assert(space >= 0);
2793 if (space == 0 || statelen >= space)
2794 goto the_end;
2795
2796#ifndef DISABLE_BROWSER
2797 if (path != NULL)
2798 prefix = _("DIR:");
2799 else
2800#endif
2801 if (filename[0] == '\0') {
2802 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002803 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002804 } else
2805 prefix = _("File:");
2806 assert(statelen < space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002807 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002808 /* If newfie is FALSE, we need a space after prefix. */
2809 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002810 prefixlen++;
2811
2812 if (path == NULL)
2813 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002814 if (space >= prefixlen + statelen)
2815 space -= prefixlen + statelen;
2816 else
2817 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002818 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002819 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002820 size_t lenpt = strlenpt(path), start_col;
2821
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002822 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002823
2824 if (dots) {
2825 start_col = lenpt - space + 3;
2826 space -= 3;
2827 } else
2828 start_col = 0;
2829
2830 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002831 }
2832
2833 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002834 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2835 /* The length of the expanded filename. */
2836
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002837 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002838 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002839 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002840 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002841 assert(strlenpt(prefix) + 1 == prefixlen);
2842
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002843 waddch(topwin, ' ');
2844 waddstr(topwin, exppath);
2845 }
2846 } else {
2847 /* We will say something like "File: ...ename". */
2848 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002849 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002850 goto the_end;
2851 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002852 waddnstr(topwin, "...", space + 3);
2853 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002854 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002855 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002856 }
2857
2858 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002859 free(exppath);
2860
2861 if (COLS <= 1 || statelen >= COLS - 1)
2862 mvwaddnstr(topwin, 0, 0, state, COLS);
2863 else {
2864 assert(COLS - statelen - 2 >= 0);
2865 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2866 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2867 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002868
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002869 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002870
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002871 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002872 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002873 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002874}
2875
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002876/* If modified is not already set, set it and update titlebar. */
2877void set_modified(void)
2878{
2879 if (!ISSET(MODIFIED)) {
2880 SET(MODIFIED);
2881 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002882 }
2883}
2884
2885void statusbar(const char *msg, ...)
2886{
2887 va_list ap;
2888
2889 va_start(ap, msg);
2890
2891 /* Curses mode is turned off. If we use wmove() now, it will muck
2892 * up the terminal settings. So we just use vfprintf(). */
2893 if (curses_ended) {
2894 vfprintf(stderr, msg, ap);
2895 va_end(ap);
2896 return;
2897 }
2898
2899 /* Blank out the line. */
2900 blank_statusbar();
2901
2902 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002903 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002904 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002905#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002906 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002907
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002908 UNSET(WHITESPACE_DISPLAY);
2909#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002910 bar = charalloc(COLS - 3);
2911 vsnprintf(bar, COLS - 3, msg, ap);
2912 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002913 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002914#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2915 if (old_whitespace)
2916 SET(WHITESPACE_DISPLAY);
2917#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002918 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002919 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002920 start_x = (COLS - foo_len - 4) / 2;
2921
2922 wmove(bottomwin, 0, start_x);
2923 wattron(bottomwin, A_REVERSE);
2924
2925 waddstr(bottomwin, "[ ");
2926 waddstr(bottomwin, foo);
2927 free(foo);
2928 waddstr(bottomwin, " ]");
2929 wattroff(bottomwin, A_REVERSE);
2930 wnoutrefresh(bottomwin);
2931 reset_cursor();
2932 wrefresh(edit);
2933 /* Leave the cursor at its position in the edit window, not
2934 * in the statusbar. */
2935 }
2936
2937 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002938 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002939}
2940
Chris Allegretta6232d662002-05-12 19:52:15 +00002941void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002942{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002943 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002944
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002945 if (ISSET(NO_HELP))
2946 return;
2947
Chris Allegretta6232d662002-05-12 19:52:15 +00002948 if (s == main_list) {
2949 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002950 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002951 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002952 slen = length_of_list(s);
2953
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002954 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002955 if (slen > MAIN_VISIBLE)
2956 slen = MAIN_VISIBLE;
2957 }
2958
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002959 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002960 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002961 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002962
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002963 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002964
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002965 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002966 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002967
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002968 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002969#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002970 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002971 keystr = _("Up");
2972 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002973#endif
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00002974 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002975
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002976 if (s->ctrlval == NANO_CONTROL_SPACE)
2977 strcpy(foo, "^ ");
2978 else if (s->ctrlval == NANO_CONTROL_8)
2979 strcpy(foo, "^?");
2980 /* Normal values. Assume that the shortcut has an
2981 * equivalent control key, meta key sequence, or both. */
2982 else if (s->ctrlval != NANO_NO_KEY)
2983 sprintf(foo, "^%c", s->ctrlval + 64);
2984 else if (s->metaval != NANO_NO_KEY)
2985 sprintf(foo, "M-%c", toupper(s->metaval));
2986
2987 keystr = foo;
2988#ifndef NANO_SMALL
2989 }
2990#endif
2991
2992 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002993 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002994 }
2995
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002996 wnoutrefresh(bottomwin);
2997 reset_cursor();
2998 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002999}
3000
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003001/* Write a shortcut key to the help area at the bottom of the window.
3002 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
3003 * to write at most len characters, even if len is very small and
3004 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
3005 * the whole string! We do not bother padding the entry with blanks. */
3006void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003007{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003008 size_t keystroke_len = strlenpt(keystroke) + 1;
3009
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00003010 assert(keystroke != NULL && desc != NULL);
3011
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003012 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003013 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003014 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003015
3016 if (len > keystroke_len)
3017 len -= keystroke_len;
3018 else
3019 len = 0;
3020
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003021 if (len > 0) {
3022 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003023 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003024 }
3025}
3026
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003027/* And so start the display update routines. */
3028
3029#ifndef NDEBUG
3030int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003031{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003032 int check_line = 0;
3033 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00003034
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003035 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
3036 check_line++;
3037 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00003038}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003039#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00003040
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003041/* nano scrolls horizontally within a line in chunks. This function
3042 * returns the column number of the first character displayed in the
3043 * window when the cursor is at the given column. Note that
3044 * 0 <= column - get_page_start(column) < COLS. */
3045size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00003046{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003047 assert(COLS > 0);
3048 if (column == 0 || column < COLS - 1)
3049 return 0;
3050 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00003051 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003052 else if (COLS > 2)
3053 return column - (COLS - 2);
3054 else
3055 return column - (COLS - 1);
3056 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003057}
3058
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003059/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003060 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003061void reset_cursor(void)
3062{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003063 /* If we haven't opened any files yet, put the cursor in the top
3064 * left corner of the edit window and get out. */
3065 if (edittop == NULL || current == NULL) {
3066 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003067 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003068 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003069
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003070 current_y = current->lineno - edittop->lineno;
3071 if (current_y < editwinrows) {
3072 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003073 wmove(edit, current_y, x - get_page_start(x));
3074 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003075}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003076
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003077/* edit_add() takes care of the job of actually painting a line into the
3078 * edit window. fileptr is the line to be painted, at row yval of the
3079 * window. converted is the actual string to be written to the window,
3080 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003081 * characters. start is the column number of the first character of
3082 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003083 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003084void edit_add(const filestruct *fileptr, const char *converted, int
3085 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003086{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003087#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
3088 size_t startpos = actual_x(fileptr->data, start);
3089 /* The position in fileptr->data of the leftmost character
3090 * that displays at least partially on the window. */
3091 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3092 /* The position in fileptr->data of the first character that is
3093 * completely off the window to the right.
3094 *
3095 * Note that endpos might be beyond the null terminator of the
3096 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003097#endif
3098
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003099 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003100 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003101
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003102 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003103 * just the text that needs it). */
3104 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003105
Chris Allegretta7dd77682001-12-08 19:52:28 +00003106#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00003107 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003108 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003109
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003110 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3111 int x_start;
3112 /* Starting column for mvwaddnstr. Zero-based. */
3113 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003114 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003115 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003116 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003117 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003118 regmatch_t startmatch; /* match position for start_regexp */
3119 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003120
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003121 if (tmpcolor->bright)
3122 wattron(edit, A_BOLD);
3123 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003124 /* Two notes about regexec(). Return value 0 means there is
3125 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003126 * after the match. */
3127
3128 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003129 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003130 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003131
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003132 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003133 * last match. Even though two matches may overlap, we
3134 * want to ignore them, so that we can highlight
3135 * C-strings correctly. */
3136 while (k < endpos) {
3137 /* Note the fifth parameter to regexec(). It says
3138 * not to match the beginning-of-line character
3139 * unless k is 0. If regexec() returns REG_NOMATCH,
3140 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003141 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003142 &startmatch, k == 0 ? 0 :
3143 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003144 break;
3145 /* Translate the match to the beginning of the line. */
3146 startmatch.rm_so += k;
3147 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003148 if (startmatch.rm_so == startmatch.rm_eo) {
3149 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00003150 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003151 } else if (startmatch.rm_so < endpos &&
3152 startmatch.rm_eo > startpos) {
3153 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003154 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003155 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003156 x_start = strnlenpt(fileptr->data,
3157 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003158
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003159 index = actual_x(converted, x_start);
3160
3161 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003162 strnlenpt(fileptr->data,
3163 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003164
3165 assert(0 <= x_start && 0 <= paintlen);
3166
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003167 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003168 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003169 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003170 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003171 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003172 } else {
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003173 /* This is a multi-line regexp. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003174 * First, we have to see if the beginning of the line is
3175 * colored by a start on an earlier line, and an end on
3176 * this line or later.
3177 *
3178 * We find the first line before fileptr matching the
3179 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003180 * end, then go to step two. Otherwise, find the next
3181 * line after start_line matching the end. If that line
3182 * is not before fileptr, then paint the beginning of
3183 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003184 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003185 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003186 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003187 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003188 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003189
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003190 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003191 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003192 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003193 /* If there is an end on this line, there is no need
3194 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003195 if (regexec(tmpcolor->end, start_line->data, 0,
3196 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003197 goto step_two;
3198 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003199 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003200 /* No start found, so skip to the next step. */
3201 if (start_line == NULL)
3202 goto step_two;
3203 /* Now start_line is the first line before fileptr
3204 * containing a start match. Is there a start on this
3205 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003206 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003207 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003208 start_col += startmatch.rm_so;
3209 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003210 if (regexec(tmpcolor->end, start_line->data +
3211 start_col + startmatch.rm_eo, 0, NULL,
3212 start_col + startmatch.rm_eo == 0 ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003213 REG_NOTBOL) == REG_NOMATCH)
3214 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003215 break;
3216 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003217 if (regexec(&tmpcolor->start, start_line->data +
3218 start_col, 1, &startmatch,
3219 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003220 /* No later start on this line. */
3221 goto step_two;
3222 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003223 /* Indeed, there is a start not followed on this line by
3224 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003225
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003226 /* We have already checked that there is no end before
3227 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003228 * the start at all? We don't paint unterminated
3229 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003230 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003231 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003232 regexec(tmpcolor->end, end_line->data, 1,
3233 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003234 end_line = end_line->next;
3235
3236 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003237 if (end_line == NULL || (end_line == fileptr &&
3238 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003239 goto step_two;
3240
3241 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003242 if (end_line != fileptr)
3243 /* If the start of fileptr is on a different line
3244 * from the end, paintlen is -1, meaning that
3245 * everything on the line gets painted. */
3246 paintlen = -1;
3247 else
3248 /* Otherwise, paintlen is the expanded location of
3249 * the end of the match minus the expanded location
3250 * of the beginning of the page. */
3251 paintlen = actual_x(converted,
3252 strnlenpt(fileptr->data, endmatch.rm_eo) -
3253 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003254
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003255 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003256
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003257 step_two:
3258 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003259 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003260
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003261 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003262 if (regexec(&tmpcolor->start,
3263 fileptr->data + start_col, 1, &startmatch,
3264 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
3265 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003266 /* No more starts on this line. */
3267 break;
3268 /* Translate the match to be relative to the
3269 * beginning of the line. */
3270 startmatch.rm_so += start_col;
3271 startmatch.rm_eo += start_col;
3272
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003273 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003274 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003275 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003276 x_start = strnlenpt(fileptr->data,
3277 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003278
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003279 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003280
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003281 if (regexec(tmpcolor->end,
3282 fileptr->data + startmatch.rm_eo, 1, &endmatch,
3283 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003284 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003285 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003286 endmatch.rm_so += startmatch.rm_eo;
3287 endmatch.rm_eo += startmatch.rm_eo;
3288 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003289 * appear on this page, and is the match more
3290 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003291 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003292 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003293 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003294 strnlenpt(fileptr->data,
3295 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003296
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003297 assert(0 <= x_start && x_start < COLS);
3298
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003299 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003300 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003301 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003302 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003303 /* There is no end on this line. But we haven't
3304 * yet looked for one on later lines. */
3305 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003306
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003307 while (end_line != NULL &&
3308 regexec(tmpcolor->end, end_line->data,
3309 0, NULL, 0) == REG_NOMATCH)
3310 end_line = end_line->next;
3311
3312 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003313 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003314
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003315 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003316 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003317 /* We painted to the end of the line, so
3318 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003319 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003320 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003321 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003322 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003323 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003324 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003325
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003326 wattroff(edit, A_BOLD);
3327 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
3328 } /* for tmpcolor in colorstrings */
3329 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003330#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003331
Chris Allegretta7dd77682001-12-08 19:52:28 +00003332#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003333 if (ISSET(MARK_ISSET)
3334 && (fileptr->lineno <= mark_beginbuf->lineno
3335 || fileptr->lineno <= current->lineno)
3336 && (fileptr->lineno >= mark_beginbuf->lineno
3337 || fileptr->lineno >= current->lineno)) {
3338 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003339
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003340 const filestruct *top;
3341 /* Either current or mark_beginbuf, whichever is first. */
3342 size_t top_x;
3343 /* current_x or mark_beginx, corresponding to top. */
3344 const filestruct *bot;
3345 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003346 int x_start;
3347 /* Starting column for mvwaddnstr. Zero-based. */
3348 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003349 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003350 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003351 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003352 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003353
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003354 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003355
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003356 if (top->lineno < fileptr->lineno || top_x < startpos)
3357 top_x = startpos;
3358 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3359 bot_x = endpos;
3360
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003361 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003362 if (top_x < endpos && bot_x > startpos) {
3363 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003364
3365 /* x_start is the expanded location of the beginning of the
3366 * mark minus the beginning of the page. */
3367 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003368
3369 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003370 /* If the end of the mark is off the page, paintlen is
3371 * -1, meaning that everything on the line gets
3372 * painted. */
3373 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003374 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003375 /* Otherwise, paintlen is the expanded location of the
3376 * end of the mark minus the expanded location of the
3377 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003378 paintlen = strnlenpt(fileptr->data, bot_x) -
3379 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003380
3381 /* If x_start is before the beginning of the page, shift
3382 * paintlen x_start characters to compensate, and put
3383 * x_start at the beginning of the page. */
3384 if (x_start < 0) {
3385 paintlen += x_start;
3386 x_start = 0;
3387 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003388
3389 assert(x_start >= 0 && x_start <= strlen(converted));
3390
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003391 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003392
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003393 if (paintlen > 0)
3394 paintlen = actual_x(converted + index, paintlen);
3395
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003396 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003397 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003398 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003399 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003400 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003401 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003402#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003403}
3404
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003405/* Just update one line in the edit buffer. This is basically a wrapper
3406 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003407 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003408 * If fileptr != current, then index is considered 0. The line will be
3409 * displayed starting with fileptr->data[index]. Likely args are
3410 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003411void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003412{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003413 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003414 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003415 char *converted;
3416 /* fileptr->data converted to have tabs and control characters
3417 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003418 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003419
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003420 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003421
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003422 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003423
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003424 /* We assume the line numbers are valid. Is that really true? */
3425 assert(line < 0 || line == check_linenumbers(fileptr));
3426
3427 if (line < 0 || line >= editwinrows)
3428 return;
3429
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003430 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003431 mvwaddstr(edit, line, 0, hblank);
3432
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003433 /* Next, convert variables that index the line to their equivalent
3434 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003435 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003436 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003437
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003438 /* Expand the line, replacing tabs with spaces, and control
3439 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003440 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003441
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003442 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003443 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003444 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003445
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003446 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003447 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003448 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003449 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003450}
3451
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003452/* Return a nonzero value if we need an update after moving
3453 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003454 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003455int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003456{
3457 return
3458#ifndef NANO_SMALL
3459 ISSET(MARK_ISSET) ||
3460#endif
3461 get_page_start(old_pww) != get_page_start(placewewant);
3462}
3463
3464/* Return a nonzero value if we need an update after moving vertically.
3465 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003466 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003467int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003468{
3469 return
3470#ifndef NANO_SMALL
3471 ISSET(MARK_ISSET) ||
3472#endif
3473 get_page_start(old_pww) != get_page_start(placewewant);
3474}
3475
3476/* Scroll the edit window in the given direction and the given number
3477 * of lines, and draw new lines on the blank lines left after the
3478 * scrolling. direction is the direction to scroll, either UP or DOWN,
3479 * and nlines is the number of lines to scroll. Don't redraw the old
3480 * topmost or bottommost line (where we assume current is) before
3481 * scrolling or draw the new topmost or bottommost line after scrolling
3482 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003483 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003484void edit_scroll(updown direction, int nlines)
3485{
3486 filestruct *foo;
3487 int i, scroll_rows = 0;
3488
3489 /* Scrolling less than one line or more than editwinrows lines is
3490 * redundant, so don't allow it. */
3491 if (nlines < 1 || nlines > editwinrows)
3492 return;
3493
3494 /* Move the top line of the edit window up or down (depending on the
3495 * value of direction) nlines lines. If there are fewer lines of
3496 * text than that left, move it to the top or bottom line of the
3497 * file (depending on the value of direction). Keep track of
3498 * how many lines we moved in scroll_rows. */
3499 for (i = nlines; i > 0; i--) {
3500 if (direction == UP) {
3501 if (edittop->prev == NULL)
3502 break;
3503 edittop = edittop->prev;
3504 scroll_rows--;
3505 } else {
3506 if (edittop->next == NULL)
3507 break;
3508 edittop = edittop->next;
3509 scroll_rows++;
3510 }
3511 }
3512
3513 /* Scroll the text on the screen up or down scroll_rows lines,
3514 * depending on the value of direction. */
3515 scrollok(edit, TRUE);
3516 wscrl(edit, scroll_rows);
3517 scrollok(edit, FALSE);
3518
3519 foo = edittop;
3520 if (direction != UP) {
3521 int slines = editwinrows - nlines;
3522 for (; slines > 0 && foo != NULL; slines--)
3523 foo = foo->next;
3524 }
3525
3526 /* And draw new lines on the blank top or bottom lines of the edit
3527 * window, depending on the value of direction. Don't draw the new
3528 * topmost or new bottommost line. */
3529 while (scroll_rows != 0 && foo != NULL) {
3530 if (foo->next != NULL)
3531 update_line(foo, 0);
3532 if (direction == UP)
3533 scroll_rows++;
3534 else
3535 scroll_rows--;
3536 foo = foo->next;
3537 }
3538}
3539
3540/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003541 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003542void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003543{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003544 int do_refresh = need_vertical_update(0) ||
3545 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003546 const filestruct *foo;
3547
3548 /* If either old_current or current is offscreen, refresh the screen
3549 * and get out. */
3550 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3551 edittop->lineno + editwinrows || current->lineno <
3552 edittop->lineno || current->lineno >= edittop->lineno +
3553 editwinrows) {
3554 edit_refresh();
3555 return;
3556 }
3557
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003558 /* Update old_current and current if we're not on the first page
3559 * and/or we're not on the same page as before. If the mark is on,
3560 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003561 foo = old_current;
3562 while (foo != current) {
3563 if (do_refresh)
3564 update_line(foo, 0);
3565#ifndef NANO_SMALL
3566 if (!ISSET(MARK_ISSET))
3567#endif
3568 break;
3569 if (foo->lineno > current->lineno)
3570 foo = foo->prev;
3571 else
3572 foo = foo->next;
3573 }
3574 if (do_refresh)
3575 update_line(current, current_x);
3576}
3577
Chris Allegretta6df90f52002-07-19 01:08:59 +00003578/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003579void edit_refresh(void)
3580{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003581 if (current->lineno < edittop->lineno ||
3582 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003583 /* Note that edit_update() changes edittop so that it's in range
3584 * of current. Thus, when it then calls edit_refresh(), there
3585 * is no danger of getting an infinite loop. */
3586 edit_update(
3587#ifndef NANO_SMALL
3588 ISSET(SMOOTHSCROLL) ? NONE :
3589#endif
3590 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003591 else {
3592 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003593 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003594
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003595#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003596 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003597#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003598
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003599 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003600 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003601 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003602 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003603 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003604 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003605 }
3606 while (nlines < editwinrows) {
3607 mvwaddstr(edit, nlines, 0, hblank);
3608 nlines++;
3609 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003610 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003611 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003612 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003613}
3614
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003615/* A nice generic routine to update the edit buffer. We keep current in
3616 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003617void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003618{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003619 filestruct *foo = current;
3620
Chris Allegretta6df90f52002-07-19 01:08:59 +00003621 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003622 /* If location is CENTER, we move edittop up (editwinrows / 2)
3623 * lines. This puts current at the center of the screen. If
3624 * location is NONE, we move edittop up current_y lines if
3625 * current_y is in range of the screen, 0 lines if current_y is
3626 * less than 0, or (editwinrows - 1) lines if current_y is
3627 * greater than (editwinrows - 1). This puts current at the
3628 * same place on the screen as before, or at the top or bottom
3629 * of the screen if edittop is beyond either. */
3630 int goal;
3631
3632 if (location == CENTER)
3633 goal = editwinrows / 2;
3634 else {
3635 goal = current_y;
3636
3637 /* Limit goal to (editwinrows - 1) lines maximum. */
3638 if (goal > editwinrows - 1)
3639 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003640 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003641
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003642 for (; goal > 0 && foo->prev != NULL; goal--)
3643 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003644 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003645
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003646 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003647 edit_refresh();
3648}
3649
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003650/* Ask a simple yes/no question, specified in msg, on the statusbar.
3651 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3652 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003653int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003654{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003655 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003656 const char *yesstr; /* String of yes characters accepted. */
3657 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003658 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003659
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003660 /* yesstr, nostr, and allstr are strings of any length. Each string
3661 * consists of all characters accepted as a valid character for that
3662 * value. The first value will be the one displayed in the
3663 * shortcuts. Translators: if possible, specify both the shortcuts
3664 * for your language and English. For example, in French: "OoYy"
3665 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003666 yesstr = _("Yy");
3667 nostr = _("Nn");
3668 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003669
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003670 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003671 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003672
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003673 if (COLS < 32)
3674 width = COLS / 2;
3675
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003676 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003677 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003678
Chris Allegretta6232d662002-05-12 19:52:15 +00003679 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003680 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003681 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003682
3683 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003684 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003685 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003686 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003687 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003688
Chris Allegrettadb28e962003-01-28 01:23:40 +00003689 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003690 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003691 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003692
Chris Allegrettadb28e962003-01-28 01:23:40 +00003693 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003694 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003695 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003696
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003697 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003698
3699 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003700 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003701
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003702 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003703
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003704 wrefresh(bottomwin);
3705
Chris Allegrettadb28e962003-01-28 01:23:40 +00003706 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003707 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003708 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003709#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003710 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003711#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003712
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003713 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003714
3715 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003716 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003717#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003718 /* Look, ma! We get to duplicate lots of code from
3719 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003720 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003721 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003722
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003723 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003724 wenclose(bottomwin, mouse_y, mouse_x) &&
3725 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003726 int x = mouse_x / width;
3727 /* Did we click in the first column of shortcuts, or
3728 * the second? */
3729 int y = mouse_y - editwinrows - 3;
3730 /* Did we click in the first row of shortcuts? */
3731
3732 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3733
3734 /* x = 0 means they clicked Yes or No.
3735 * y = 0 means Yes or All. */
3736 ok = -2 * x * y + x - y + 1;
3737
3738 if (ok == 2 && !all)
3739 ok = -2;
3740 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003741 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003742#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003743 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003744 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003745 else if (strchr(yesstr, kbinput) != NULL)
3746 ok = 1;
3747 else if (strchr(nostr, kbinput) != NULL)
3748 ok = 0;
3749 else if (all && strchr(allstr, kbinput) != NULL)
3750 ok = 2;
3751 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003752
Chris Allegrettadb28e962003-01-28 01:23:40 +00003753 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003754}
3755
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003756void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003757{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003758 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003759 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003760 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003761 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003762 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003763 wnoutrefresh(bottomwin);
3764 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003765 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003766 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003767 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003768 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003769 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003770 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003771}
3772
3773void display_main_list(void)
3774{
3775 bottombars(main_list);
3776}
3777
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003778/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3779 * display the cursor position. Otherwise, we display it only if the
3780 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003781 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003782 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3783 * old_i and old_totsize. That way, we leave the current statusbar
3784 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003785void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003786{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003787 char c;
3788 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003789 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003790 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003791
Chris Allegrettad26ab912003-01-28 01:16:47 +00003792 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003793
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003794 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003795 old_totsize = totsize;
3796
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003797 c = current->data[current_x];
3798 f = current->next;
3799 current->data[current_x] = '\0';
3800 current->next = NULL;
3801 get_totals(fileage, current, NULL, &i);
3802 current->data[current_x] = c;
3803 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003804
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003805 /* Check whether totsize is correct. Else there is a bug
3806 * somewhere. */
3807 assert(current != filebot || i == totsize);
3808
Chris Allegrettad26ab912003-01-28 01:16:47 +00003809 if (constant && ISSET(DISABLE_CURPOS)) {
3810 UNSET(DISABLE_CURPOS);
3811 old_i = i;
3812 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003813 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003814 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003815
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003816 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003817 * unconditionally; otherwise, only display the position when the
3818 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003819 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003820 size_t xpt = xplustabs() + 1;
3821 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003822 int linepct = 100 * current->lineno / totlines;
3823 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003824 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003825
3826 statusbar(
3827 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3828 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003829 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003830 (unsigned long)i, (unsigned long)totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003831 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003832 }
3833
3834 old_i = i;
3835 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003836}
3837
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003838void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003839{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003840 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003841}
3842
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003843#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003844/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003845int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003846{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003847 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003848
3849 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3850 ptr++;
3851 j++;
3852 }
3853 if (j == COLS - 5) {
3854 /* Don't wrap at the first of two spaces following a period. */
3855 if (*ptr == ' ' && *(ptr + 1) == ' ')
3856 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003857 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003858 while (*ptr != ' ' && j > 0) {
3859 ptr--;
3860 j--;
3861 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003862 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003863 if (j == 0)
3864 j = COLS - 5;
3865 }
3866 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
3867 return j;
3868}
3869
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003870/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003871void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003872{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003873 int line = 0;
3874 /* The line number in help_text of the first displayed help line.
3875 * This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003876 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003877 /* no_more means the end of the help text is shown, so don't go
3878 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003879 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003880 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003881
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003882 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003883#ifndef DISABLE_MOUSE
3884 const shortcut *oldshortcut = currshortcut;
3885 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003886 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003887#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003888
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003889 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003890 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003891 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003892 blank_statusbar();
3893
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003894 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003895 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003896 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003897
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003898#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003899 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003900 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003901 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003902#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003903
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003904 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003905 /* Make sure that the help screen's shortcut list will actually
3906 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003907 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003908 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003909 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003910
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003911 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003912
3913 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003914 int i;
3915 int old_line = line;
3916 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003917 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003918
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003919 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003920#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003921 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003922 {
3923 int mouse_x, mouse_y;
3924 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3925 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003926 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003927#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003928 case NANO_NEXTPAGE_KEY:
3929 case NANO_NEXTPAGE_FKEY:
3930 if (!no_more)
3931 line += editwinrows - 2;
3932 break;
3933 case NANO_PREVPAGE_KEY:
3934 case NANO_PREVPAGE_FKEY:
3935 if (line > 0) {
3936 line -= editwinrows - 2;
3937 if (line < 0)
3938 line = 0;
3939 }
3940 break;
3941 case NANO_PREVLINE_KEY:
3942 if (line > 0)
3943 line--;
3944 break;
3945 case NANO_NEXTLINE_KEY:
3946 if (!no_more)
3947 line++;
3948 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003949 }
3950
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003951 if (line == old_line && kbinput != ERR)
3952 goto skip_redisplay;
3953
3954 blank_edit();
3955
3956 assert(COLS > 5);
3957
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003958 /* Calculate where in the text we should be, based on the
3959 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003960 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003961 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003962 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003963 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003964 }
3965
Chris Allegretta4640fe32003-02-10 03:10:03 +00003966 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003967 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003968
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003969 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003970 ptr += j;
3971 if (*ptr == '\n')
3972 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003973 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003974 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003975
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003976 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003977 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003978 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3979 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003980
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003981#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003982 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003983#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003984
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003985 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003986 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003987 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003988 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003989 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003990 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003991 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003992
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003993 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003994 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003995
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003996 /* The help_init() at the beginning allocated help_text. Since
3997 * help_text has now been written to the screen, we don't need it
3998 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003999 free(help_text);
4000 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004001}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00004002#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004003
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004004/* Highlight the current word being replaced or spell checked. We
4005 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00004006void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00004007{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00004008 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004009 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004010
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004011 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004012 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004013 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00004014
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004015 assert(y > 0);
4016
4017 if (word_len > y)
4018 y--;
4019
Chris Allegrettafb62f732000-12-05 11:36:41 +00004020 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00004021
Chris Allegrettafb62f732000-12-05 11:36:41 +00004022 if (highlight_flag)
4023 wattron(edit, A_REVERSE);
4024
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004025#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00004026 /* This is so we can show zero-length regexes. */
4027 if (word_len == 0)
4028 waddstr(edit, " ");
4029 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004030#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004031 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004032
4033 if (word_len > y)
4034 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00004035
4036 if (highlight_flag)
4037 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004038}
4039
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004040#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004041/* Dump the passed-in file structure to stderr. */
4042void dump_buffer(const filestruct *inptr)
4043{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004044 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004045 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004046 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004047 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004048 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00004049 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004050
4051 while (inptr != NULL) {
4052 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4053 inptr = inptr->next;
4054 }
4055}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004056
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004057/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004058void dump_buffer_reverse(void)
4059{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004060 const filestruct *fileptr = filebot;
4061
4062 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004063 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004064 fileptr = fileptr->prev;
4065 }
4066}
4067#endif /* DEBUG */
4068
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004069#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004070#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004071#define XLCREDIT_LEN 8
4072
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004073/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004074void do_credits(void)
4075{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004076 int crpos = 0, xlpos = 0;
4077 const char *credits[CREDIT_LEN] = {
4078 NULL, /* "The nano text editor" */
4079 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004080 VERSION,
4081 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004082 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004083 "Chris Allegretta",
4084 "Jordi Mallach",
4085 "Adam Rogoyski",
4086 "Rob Siemborski",
4087 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004088 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004089 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004090 "Ken Tyler",
4091 "Sven Guckes",
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004092#ifdef NANO_WIDE
David Lawrence Ramsey487d08c2005-01-12 18:16:17 +00004093 !ISSET(NO_UTF8) ? "Florian König" :
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004094#endif
4095 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00004096 "Pauli Virtanen",
4097 "Daniele Medri",
4098 "Clement Laforet",
4099 "Tedi Heriyanto",
4100 "Bill Soudan",
4101 "Christian Weisgerber",
4102 "Erik Andersen",
4103 "Big Gaute",
4104 "Joshua Jensen",
4105 "Ryan Krebs",
4106 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004107 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004108 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004109 "Plattsburgh State University",
4110 "Benet Laboratories",
4111 "Amy Allegretta",
4112 "Linda Young",
4113 "Jeremy Robichaud",
4114 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004115 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004116 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004117 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004118 "Thomas Dickey",
4119 "Pavel Curtis",
4120 "Zeyd Ben-Halim",
4121 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004122 NULL, /* "and anyone else we forgot..." */
4123 NULL, /* "Thank you for using nano!" */
4124 "",
4125 "",
4126 "",
4127 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004128 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004129 "",
4130 "",
4131 "",
4132 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004133 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004134 };
4135
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004136 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004137 N_("The nano text editor"),
4138 N_("version"),
4139 N_("Brought to you by:"),
4140 N_("Special thanks to:"),
4141 N_("The Free Software Foundation"),
4142 N_("For ncurses:"),
4143 N_("and anyone else we forgot..."),
4144 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004145 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004146
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004147 curs_set(0);
4148 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004149 scrollok(edit, TRUE);
4150 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004151 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004152 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004153 blank_statusbar();
4154 blank_bottombars();
4155 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004156 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004157 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004158
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004159 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
4160 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004161 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004162 if (crpos < CREDIT_LEN) {
4163 const char *what = credits[crpos];
4164 size_t start_x;
4165
4166 if (what == NULL) {
4167 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00004168 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004169 xlpos++;
4170 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004171 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramseyeb711b02004-12-05 22:24:39 +00004172 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x,
4173 what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004174 }
4175 napms(700);
4176 scroll(edit);
4177 wrefresh(edit);
4178 if (wgetch(edit) != ERR)
4179 break;
4180 napms(700);
4181 scroll(edit);
4182 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004183 }
4184
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004185 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004186 nodelay(edit, FALSE);
4187 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004188 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004189}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004190#endif