blob: 522a79ed869d794c58c99c90fc7dd7e3dfbccd74 [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 Ramseyc275dc52005-03-08 17:45:36 +0000143 /* If we get ERR when using blocking input, it means that the input
144 * source that we were using is gone, so die gracefully. */
145 if (input == ERR)
146 handle_hupterm(0);
147
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000148#ifndef NANO_SMALL
149 allow_pending_sigwinch(FALSE);
150#endif
151
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000152 /* Increment the length of the keystroke buffer, save the value of
153 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000154 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000155 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000156 key_buffer = (int *)nmalloc(sizeof(int));
157 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000158
159 /* Read in the remaining characters using non-blocking input. */
160 nodelay(win, TRUE);
161
162 while (TRUE) {
163#ifndef NANO_SMALL
164 allow_pending_sigwinch(TRUE);
165#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000166
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000167 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000168
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000169 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000170 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000171 break;
172
173 /* Otherwise, increment the length of the keystroke buffer, save
174 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000175 * if the keystroke is an extended keypad value or FALSE if it
176 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000177 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000178 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
179 sizeof(int));
180 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000181
182#ifndef NANO_SMALL
183 allow_pending_sigwinch(FALSE);
184#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000185 }
186
187 /* Switch back to non-blocking input. */
188 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000189}
190
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000191/* Return the length of the default keystroke buffer. */
192size_t get_buffer_len(void)
193{
194 return key_buffer_len;
195}
196
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000197/* Add the contents of the keystroke buffer input to the default
198 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000199void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000200{
201#ifndef NANO_SMALL
202 allow_pending_sigwinch(TRUE);
203 allow_pending_sigwinch(FALSE);
204#endif
205
206 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000207 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000208 return;
209
210 /* If adding input would put the default keystroke buffer beyond
211 * maximum capacity, only add enough of input to put it at maximum
212 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000213 if (key_buffer_len + input_len < key_buffer_len)
214 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000215
216 /* Add the length of input to the length of the default keystroke
217 * buffer, and reallocate the default keystroke buffer so that it
218 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000219 key_buffer_len += input_len;
220 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
221 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000222
223 /* If the default keystroke buffer wasn't empty before, move its
224 * beginning forward far enough so that we can add input to its
225 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000226 if (key_buffer_len > input_len)
227 memmove(key_buffer + input_len, key_buffer,
228 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000229
230 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000231 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000232}
233
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000234/* Put back the character stored in kbinput, putting it in byte range
235 * beforehand. If meta_key is TRUE, put back the Escape character after
236 * putting back kbinput. If func_key is TRUE, put back the function key
237 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000238void unget_kbinput(int kbinput, bool meta_key, bool func_key)
239{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000240 if (!func_key)
241 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000242
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000243 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000244
245 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000246 kbinput = NANO_CONTROL_3;
247 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000248 }
249}
250
251/* Try to read input_len characters from the default keystroke buffer.
252 * If the default keystroke buffer is empty and win isn't NULL, try to
253 * read in more characters from win and add them to the default
254 * keystroke buffer before doing anything else. If the default
255 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000256int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000257{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000258 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000259
260#ifndef NANO_SMALL
261 allow_pending_sigwinch(TRUE);
262 allow_pending_sigwinch(FALSE);
263#endif
264
265 if (key_buffer_len == 0) {
266 if (win != NULL)
267 get_buffer(win);
268
269 if (key_buffer_len == 0)
270 return NULL;
271 }
272
273 /* If input_len is greater than the length of the default keystroke
274 * buffer, only read the number of characters in the default
275 * keystroke buffer. */
276 if (input_len > key_buffer_len)
277 input_len = key_buffer_len;
278
279 /* Subtract input_len from the length of the default keystroke
280 * buffer, and allocate the keystroke buffer input so that it
281 * has enough room for input_len keystrokes. */
282 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000283 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000284
285 /* Copy input_len characters from the beginning of the default
286 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000287 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000288
289 /* If the default keystroke buffer is empty, mark it as such. */
290 if (key_buffer_len == 0) {
291 free(key_buffer);
292 key_buffer = NULL;
293 /* If the default keystroke buffer isn't empty, move its
294 * beginning forward far enough back so that the keystrokes in input
295 * are no longer at its beginning. */
296 } else {
297 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000298 sizeof(int));
299 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
300 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000301 }
302
303 return input;
304}
305
306/* Read in a single character. If it's ignored, swallow it and go on.
307 * Otherwise, try to translate it from ASCII, meta key sequences, escape
308 * sequences, and/or extended keypad values. Set meta_key to TRUE when
309 * we get a meta key sequence, and set func_key to TRUE when we get an
310 * extended keypad value. Supported extended keypad values consist of
311 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
312 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
313 * the function keypad (F1-F16), and the numeric keypad with NumLock
314 * off. Assume nodelay(win) is FALSE. */
315int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
316{
317 int kbinput;
318
319 /* Read in a character and interpret it. Continue doing this until
320 * we get a recognized value or sequence. */
321 while ((kbinput = parse_kbinput(win, meta_key, func_key
322#ifndef NANO_SMALL
323 , FALSE
324#endif
325 )) == ERR);
326
327 return kbinput;
328}
329
330/* Translate ASCII characters, extended keypad values, and escape
331 * sequences into their corresponding key values. Set meta_key to TRUE
332 * when we get a meta key sequence, and set func_key to TRUE when we get
333 * a function key. Assume nodelay(win) is FALSE. */
334int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000335#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000336 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000337#endif
338 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000339
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000340{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000341 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000342 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000343
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000344#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000345 if (reset) {
346 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000347 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000348 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000349 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000350#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000351
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000352 *meta_key = FALSE;
353 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000354
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000355 /* Read in a character. */
356 while ((kbinput = get_input(win, 1)) == NULL);
357
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000358 switch (*kbinput) {
359 case ERR:
360 break;
361 case NANO_CONTROL_3:
362 /* Increment the escape counter. */
363 escapes++;
364 switch (escapes) {
365 case 1:
366 /* One escape: wait for more input. */
367 case 2:
368 /* Two escapes: wait for more input. */
369 break;
370 default:
371 /* More than two escapes: reset the escape counter
372 * and wait for more input. */
373 escapes = 0;
374 }
375 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000376#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000377 /* Since we don't change the default SIGWINCH handler when
378 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
379 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
380 case KEY_RESIZE:
381 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000382#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000383#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000384 case KEY_SHIFT_L:
385 case KEY_SHIFT_R:
386 case KEY_CONTROL_L:
387 case KEY_CONTROL_R:
388 case KEY_ALT_L:
389 case KEY_ALT_R:
390 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000391#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000392 default:
393 switch (escapes) {
394 case 0:
395 switch (*kbinput) {
396 case NANO_CONTROL_8:
397 retval = ISSET(REBIND_DELETE) ?
398 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
399 break;
400 case KEY_DOWN:
401 retval = NANO_NEXTLINE_KEY;
402 break;
403 case KEY_UP:
404 retval = NANO_PREVLINE_KEY;
405 break;
406 case KEY_LEFT:
407 retval = NANO_BACK_KEY;
408 break;
409 case KEY_RIGHT:
410 retval = NANO_FORWARD_KEY;
411 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000412#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000413 /* HP-UX 10 and 11 don't support KEY_HOME. */
414 case KEY_HOME:
415 retval = NANO_HOME_KEY;
416 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000417#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000418 case KEY_BACKSPACE:
419 retval = NANO_BACKSPACE_KEY;
420 break;
421 case KEY_DC:
422 retval = ISSET(REBIND_DELETE) ?
423 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
424 break;
425 case KEY_IC:
426 retval = NANO_INSERTFILE_KEY;
427 break;
428 case KEY_NPAGE:
429 retval = NANO_NEXTPAGE_KEY;
430 break;
431 case KEY_PPAGE:
432 retval = NANO_PREVPAGE_KEY;
433 break;
434 case KEY_ENTER:
435 retval = NANO_ENTER_KEY;
436 break;
437 case KEY_A1: /* Home (7) on numeric keypad
438 * with NumLock off. */
439 retval = NANO_HOME_KEY;
440 break;
441 case KEY_A3: /* PageUp (9) on numeric keypad
442 * with NumLock off. */
443 retval = NANO_PREVPAGE_KEY;
444 break;
445 case KEY_B2: /* Center (5) on numeric keypad
446 * with NumLock off. */
447 break;
448 case KEY_C1: /* End (1) on numeric keypad
449 * with NumLock off. */
450 retval = NANO_END_KEY;
451 break;
452 case KEY_C3: /* PageDown (4) on numeric
453 * keypad with NumLock off. */
454 retval = NANO_NEXTPAGE_KEY;
455 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000456#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000457 /* Slang doesn't support KEY_BEG. */
458 case KEY_BEG: /* Center (5) on numeric keypad
459 * with NumLock off. */
460 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000461#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000462#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000463 /* HP-UX 10 and 11 don't support KEY_END. */
464 case KEY_END:
465 retval = NANO_END_KEY;
466 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000467#endif
468#ifdef KEY_SUSPEND
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000469 /* Slang doesn't support KEY_SUSPEND. */
470 case KEY_SUSPEND:
471 retval = NANO_SUSPEND_KEY;
472 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000473#endif
474#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000475 /* Slang doesn't support KEY_SLEFT. */
476 case KEY_SLEFT:
477 retval = NANO_BACK_KEY;
478 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000479#endif
480#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000481 /* Slang doesn't support KEY_SRIGHT. */
482 case KEY_SRIGHT:
483 retval = NANO_FORWARD_KEY;
484 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000485#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000486 default:
487 retval = *kbinput;
488 break;
489 }
490 break;
491 case 1:
492 /* One escape followed by a non-escape: escape
493 * sequence mode. Reset the escape counter. If
494 * there aren't any other keys waiting, we have a
495 * meta key sequence, so set meta_key to TRUE and
496 * save the lowercase version of the non-escape
497 * character as the result. If there are other keys
498 * waiting, we have a true escape sequence, so
499 * interpret it. */
500 escapes = 0;
501 if (get_buffer_len() == 0) {
502 *meta_key = TRUE;
503 retval = tolower(*kbinput);
504 } else {
505 int *seq;
506 size_t seq_len;
507 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000508
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000509 /* Put back the non-escape character, get the
510 * complete escape sequence, translate the
511 * sequence into its corresponding key value,
512 * and save that as the result. */
513 unget_input(kbinput, 1);
514 seq_len = get_buffer_len();
515 seq = get_input(NULL, seq_len);
516 retval = get_escape_seq_kbinput(seq, seq_len,
517 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000518
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000519 /* If the escape sequence is unrecognized and
520 * not ignored, put back all of its characters
521 * except for the initial escape. */
522 if (retval == ERR && !ignore_seq)
523 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000524
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000525 free(seq);
526 }
527 break;
528 case 2:
529 /* Two escapes followed by one or more decimal
530 * digits: byte sequence mode. If the word
531 * sequence's range is limited to 2XX (the first
532 * digit is in the '0' to '2' range and it's the
533 * first digit, or it's in the '0' to '9' range and
534 * it's not the first digit), increment the byte
535 * sequence counter and interpret the digit. If the
536 * byte sequence's range is not limited to 2XX, fall
537 * through. */
538 if (('0' <= *kbinput && *kbinput <= '6' &&
539 byte_digits == 0) || ('0' <= *kbinput &&
540 *kbinput <= '9' && byte_digits > 0)) {
541 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000542
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000543 byte_digits++;
544 byte = get_byte_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000545#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000546 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000547#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000548 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000549
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000550 if (byte != ERR) {
551 char *byte_mb = charalloc(mb_cur_max());
552 int byte_mb_len, *seq, i;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000553
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000554 /* If we've read in a complete byte
555 * sequence, reset the byte sequence counter
556 * and the escape counter, and put back the
557 * corresponding byte value. */
558 byte_digits = 0;
559 escapes = 0;
560
561 /* Put back the multibyte equivalent of the
562 * byte value. */
563 byte_mb = make_mbchar(byte, byte_mb,
564 &byte_mb_len);
565
566 seq = (int *)nmalloc(byte_mb_len *
567 sizeof(int));
568
569 for (i = 0; i < byte_mb_len; i++)
570 seq[i] = (unsigned char)byte_mb[i];
571
572 unget_input(seq, byte_mb_len);
573
574 free(seq);
575 free(byte_mb);
576 }
577 } else {
578 /* Reset the escape counter. */
579 escapes = 0;
580 if (byte_digits == 0)
581 /* Two escapes followed by a non-decimal
582 * digit or a decimal digit that would
583 * create a byte sequence greater than 2XX,
584 * and we're not in the middle of a byte
585 * sequence: control character sequence
586 * mode. Interpret the control sequence and
587 * save the corresponding control character
588 * as the result. */
589 retval = get_control_kbinput(*kbinput);
590 else {
591 /* If we're in the middle of a byte
592 * sequence, reset the byte sequence counter
593 * and save the character we got as the
594 * result. */
595 byte_digits = 0;
596 retval = *kbinput;
597 }
598 }
599 break;
600 }
601 }
602
603 /* If we have a result and it's an extended keypad value (i.e, a
604 * value outside of byte range), set func_key to TRUE. */
605 if (retval != ERR)
606 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000607
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000608#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000609 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 +0000610#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000611
612 /* Return the result. */
613 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000614}
615
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000616/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000617 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000618 * are generated when the keypad doesn't support the needed keys. If
619 * the escape sequence is recognized but we want to ignore it, return
620 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
621 * set ignore_seq to FALSE. Assume that Escape has already been read
622 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000623int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000624 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000625{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000626 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000627
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000628 *ignore_seq = FALSE;
629
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000630 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000631 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000632 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000633 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000634 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000635 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000636 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000637 case 'P': /* Esc O 2 P == F13 on
638 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000639 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000640 break;
641 case 'Q': /* Esc O 2 Q == F14 on
642 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000643 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000644 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000645 case 'R': /* Esc O 2 R == F15 on
646 * xterm. */
647 retval = KEY_F(15);
648 break;
649 case 'S': /* Esc O 2 S == F16 on
650 * xterm. */
651 retval = KEY_F(16);
652 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000653 }
654 }
655 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000656 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
657 case 'B': /* Esc O B == Down on
658 * VT100/VT320/xterm. */
659 case 'C': /* Esc O C == Right on
660 * VT100/VT320/xterm. */
661 case 'D': /* Esc O D == Left on
662 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000663 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000664 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000665 case 'E': /* Esc O E == Center (5) on numeric keypad
666 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000667 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000668 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000669 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000670 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000671 break;
672 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000673 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000674 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000675 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000676 * NumLock off on VT100/VT220/VT320/xterm/
677 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000678 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000679 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000680 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000681 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000682 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000683 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000684 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000685 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000686 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000687 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000688 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000689 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000690 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000691 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000692 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000693 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000694 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000695 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000696 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000697 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000698 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000699 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000700 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000701 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000702 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000703 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000704 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000705 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000706 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000707 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000708 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000709 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000710 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000711 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000712 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000713 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000714 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000715 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000716 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000717 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000718 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000719 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000720 case 'j': /* Esc O j == '*' 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 'k': /* Esc O k == '+' 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 'l': /* Esc O l == ',' 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 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000736 * NumLock off on VT100/VT220/VT320/xterm/
737 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000738 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000739 break;
740 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000741 * with NumLock off on VT100/VT220/VT320/
742 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000743 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000744 break;
745 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000746 * NumLock off on VT100/VT220/VT320/xterm/
747 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000748 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000749 break;
750 case 'p': /* Esc O p == Insert (0) 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_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000754 break;
755 case 'q': /* Esc O q == End (1) 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_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000759 break;
760 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000761 * with NumLock off on VT100/VT220/VT320/
762 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000763 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000764 break;
765 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000766 * keypad with NumLock off on VT100/VT220/
767 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000768 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000769 break;
770 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000771 * with NumLock off on VT100/VT220/VT320/
772 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000773 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000774 break;
775 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000776 * with NumLock off on VT100/VT220/VT320/
777 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000778 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000779 break;
780 case 'v': /* Esc O v == Right (6) 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_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000784 break;
785 case 'w': /* Esc O w == Home (7) 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_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000789 break;
790 case 'x': /* Esc O x == Up (8) 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_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000794 break;
795 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000796 * with NumLock off on VT100/VT220/VT320/
797 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000798 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000799 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000800 }
801 break;
802 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000803 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000804 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000805 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000806 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000807 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000808 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000809 break;
810 }
811 break;
812 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000813 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000814 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000815 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000816 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000817 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
818 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000819 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000820 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000821 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
822 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000823 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000824 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000825 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
826 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000827 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000828 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000829 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
830 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000831 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000832 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000833 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
834 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000835 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000836 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000837 case '7': /* Esc [ 1 7 ~ == F6 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(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000841 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000842 case '8': /* Esc [ 1 8 ~ == F7 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(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000846 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000847 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000848 * VT220/VT320/Linux console/
849 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000850 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000851 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000852 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000853 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000854 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000855 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000856 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000857 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000858 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
859 * xterm. */
860 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
861 * xterm. */
862 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
863 * xterm. */
864 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
865 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000866 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000867 break;
868 }
869 }
870 break;
871 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000872 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000873 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000874 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
875 * xterm. */
876 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
877 * xterm. */
878 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
879 * xterm. */
880 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
881 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000882 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000883 break;
884 }
885 }
886 break;
887 }
888 }
889 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000890 default: /* Esc [ 1 ~ == Home on
891 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000892 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000893 break;
894 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000895 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000896 break;
897 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000898 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000899 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000900 case '0': /* Esc [ 2 0 ~ == F9 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(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000904 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000905 case '1': /* Esc [ 2 1 ~ == F10 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(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000909 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000910 case '3': /* Esc [ 2 3 ~ == F11 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(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000914 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000915 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000916 * VT220/VT320/Linux console/
917 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000918 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000919 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000920 case '5': /* Esc [ 2 5 ~ == F13 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(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000924 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000925 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000926 * VT220/VT320/Linux console/
927 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000928 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000929 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000930 case '8': /* Esc [ 2 8 ~ == F15 on
931 * VT220/VT320/Linux console/
932 * rxvt/Eterm. */
933 retval = KEY_F(15);
934 break;
935 case '9': /* Esc [ 2 9 ~ == F16 on
936 * VT220/VT320/Linux console/
937 * rxvt/Eterm. */
938 retval = KEY_F(16);
939 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000940 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000941 * VT220/VT320/Linux console/
942 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000943 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000944 break;
945 }
946 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000947 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000948 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
949 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000950 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000951 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000952 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000953 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000954 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000955 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000956 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
957 * Linux console/xterm; Esc [ 5 ^ ==
958 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000959 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000960 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000961 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
962 * Linux console/xterm; Esc [ 6 ^ ==
963 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000964 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000965 break;
966 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000967 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000968 break;
969 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000970 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000971 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000972 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000973 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000974 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000975 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000976 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000977 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000978 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000979 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000980 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000981 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000982 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000983 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000984 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000985 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000986 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000987 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000988 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000989 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000990 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000991 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000992 case 'E': /* Esc [ E == Center (5) on numeric keypad
993 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000994 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000995 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000996 case 'F': /* Esc [ F == End on FreeBSD
997 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000998 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000999 break;
1000 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001001 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001002 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001003 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001004 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001005 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001006 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001007 break;
1008 case 'I': /* Esc [ I == PageUp on FreeBSD
1009 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001010 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001011 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001012 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001013 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001014 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001015 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001016 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001017 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001018 break;
1019 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001020 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001021 break;
1022 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001023 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001024 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001025 case 'P': /* Esc [ O P == F1 on
1026 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001027 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001028 break;
1029 case 'Q': /* Esc [ O Q == F2 on
1030 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001031 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001032 break;
1033 case 'R': /* Esc [ O R == F3 on
1034 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001035 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001036 break;
1037 case 'S': /* Esc [ O S == F4 on
1038 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001039 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001040 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001041 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001042 } else {
1043 /* Esc [ O == F3 on FreeBSD console. */
1044 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001045 }
1046 break;
1047 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001048 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001049 break;
1050 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001051 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001052 break;
1053 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001054 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001055 break;
1056 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001057 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001058 break;
1059 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001060 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001061 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001062 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001063 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001064 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001065 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001066 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001067 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001068 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001069 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001070 break;
1071 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001072 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001073 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001074 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001075 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001076 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001077 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001078 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001079 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001080 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001081 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001082 case 'c': /* Esc [ c == Shift-Right on rxvt/
1083 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001084 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001085 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001086 break;
1087 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001088 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001089 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001090 case 'A': /* Esc [ [ A == F1 on Linux
1091 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001092 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001093 break;
1094 case 'B': /* Esc [ [ B == F2 on Linux
1095 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001096 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001097 break;
1098 case 'C': /* Esc [ [ C == F3 on Linux
1099 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001100 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001101 break;
1102 case 'D': /* Esc [ [ D == F4 on Linux
1103 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001104 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001105 break;
1106 case 'E': /* Esc [ [ E == F5 on Linux
1107 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001108 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001109 break;
1110 }
1111 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001112 break;
1113 }
1114 break;
1115 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001116 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001117
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001118#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001119 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001120#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001121
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001122 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001123}
1124
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001125/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001126 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001127 * to many escape sequences. */
1128int get_escape_seq_abcd(int kbinput)
1129{
1130 switch (tolower(kbinput)) {
1131 case 'a':
1132 return NANO_PREVLINE_KEY;
1133 case 'b':
1134 return NANO_NEXTLINE_KEY;
1135 case 'c':
1136 return NANO_FORWARD_KEY;
1137 case 'd':
1138 return NANO_BACK_KEY;
1139 default:
1140 return ERR;
1141 }
1142}
1143
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001144/* Translate a byte sequence: turn a three-digit decimal number from
1145 * 000 to 255 into its corresponding byte value. */
1146int get_byte_kbinput(int kbinput
1147#ifndef NANO_SMALL
1148 , bool reset
1149#endif
1150 )
1151{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001152 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001153 int retval = ERR;
1154
1155#ifndef NANO_SMALL
1156 if (reset) {
1157 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001158 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001159 return ERR;
1160 }
1161#endif
1162
1163 /* Increment the byte digit counter. */
1164 byte_digits++;
1165
1166 switch (byte_digits) {
1167 case 1:
1168 /* One digit: reset the byte sequence holder and add the
1169 * digit we got to the 100's position of the byte sequence
1170 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001171 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001172 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001173 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001174 else
1175 /* If the character we got isn't a decimal digit, or if
1176 * it is and it would put the byte sequence out of byte
1177 * range, save it as the result. */
1178 retval = kbinput;
1179 break;
1180 case 2:
1181 /* Two digits: add the digit we got to the 10's position of
1182 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001183 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1184 '6' <= kbinput && kbinput <= '9'))
1185 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001186 else
1187 /* If the character we got isn't a decimal digit, or if
1188 * it is and it would put the byte sequence out of byte
1189 * range, save it as the result. */
1190 retval = kbinput;
1191 break;
1192 case 3:
1193 /* Three digits: add the digit we got to the 1's position of
1194 * the byte sequence holder, and save the corresponding word
1195 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001196 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1197 '6' <= kbinput && kbinput <= '9')) {
1198 byte += (kbinput - '0');
1199 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001200 } else
1201 /* If the character we got isn't a decimal digit, or if
1202 * it is and it would put the word sequence out of word
1203 * range, save it as the result. */
1204 retval = kbinput;
1205 break;
1206 default:
1207 /* More than three digits: save the character we got as the
1208 * result. */
1209 retval = kbinput;
1210 break;
1211 }
1212
1213 /* If we have a result, reset the byte digit counter and the byte
1214 * sequence holder. */
1215 if (retval != ERR) {
1216 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001217 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001218 }
1219
1220#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001221 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 +00001222#endif
1223
1224 return retval;
1225}
1226
1227/* Translate a word sequence: turn a four-digit hexadecimal number from
1228 * 0000 to ffff (case-insensitive) into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001229int get_word_kbinput(int kbinput
1230#ifndef NANO_SMALL
1231 , bool reset
1232#endif
1233 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001234{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001235 static int word_digits = 0, word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001236 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001237
1238#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001239 if (reset) {
1240 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001241 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001242 return ERR;
1243 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001244#endif
1245
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001246 /* Increment the word digit counter. */
1247 word_digits++;
1248
1249 switch (word_digits) {
1250 case 1:
1251 /* One digit: reset the word sequence holder and add the
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001252 * digit we got to the 4096's position of the word sequence
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001253 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001254 word = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001255 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001256 word += (kbinput - '0') * 4096;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001257 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001258 word += (tolower(kbinput) + 10 - 'a') * 4096;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001259 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001260 /* If the character we got isn't a hexadecimal digit, or
1261 * if it is and it would put the word sequence out of
1262 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001263 retval = kbinput;
1264 break;
1265 case 2:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001266 /* Two digits: add the digit we got to the 256's position of
1267 * the word sequence holder. */
1268 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001269 word += (kbinput - '0') * 256;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001270 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001271 word += (tolower(kbinput) + 10 - 'a') * 256;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001272 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001273 /* If the character we got isn't a hexadecimal digit, or
1274 * if it is and it would put the word sequence out of
1275 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001276 retval = kbinput;
1277 break;
1278 case 3:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001279 /* Three digits: add the digit we got to the 16's position
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001280 * of the word sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001281 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001282 word += (kbinput - '0') * 16;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001283 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001284 word += (tolower(kbinput) + 10 - 'a') * 16;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001285 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001286 /* If the character we got isn't a hexadecimal digit, or
1287 * if it is and it would put the word sequence out of
1288 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001289 retval = kbinput;
1290 break;
1291 case 4:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001292 /* Four digits: add the digit we got to the 1's position of
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001293 * the word sequence holder, and save the corresponding word
1294 * value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001295 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001296 word += (kbinput - '0');
1297 retval = word;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001298 } else if ('a' <= tolower(kbinput) &&
1299 tolower(kbinput) <= 'f') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001300 word += (tolower(kbinput) + 10 - 'a');
1301 retval = word;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001302 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001303 /* If the character we got isn't a hexadecimal digit, or
1304 * if it is and it would put the word sequence out of
1305 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001306 retval = kbinput;
1307 break;
1308 default:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001309 /* More than four digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001310 * result. */
1311 retval = kbinput;
1312 break;
1313 }
1314
1315 /* If we have a result, reset the word digit counter and the word
1316 * sequence holder. */
1317 if (retval != ERR) {
1318 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001319 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001320 }
1321
1322#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001323 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 +00001324#endif
1325
1326 return retval;
1327}
1328
1329/* Translate a control character sequence: turn an ASCII non-control
1330 * character into its corresponding control character. */
1331int get_control_kbinput(int kbinput)
1332{
1333 int retval;
1334
1335 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1336 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1337 kbinput == '`')
1338 retval = NANO_CONTROL_SPACE;
1339 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1340 else if ('3' <= kbinput && kbinput <= '7')
1341 retval = kbinput - 24;
1342 /* Ctrl-8 (Ctrl-?) */
1343 else if (kbinput == '8' || kbinput == '?')
1344 retval = NANO_CONTROL_8;
1345 /* Ctrl-A to Ctrl-_ */
1346 else if ('A' <= kbinput && kbinput <= '_')
1347 retval = kbinput - 64;
1348 /* Ctrl-a to Ctrl-~ */
1349 else if ('a' <= kbinput && kbinput <= '~')
1350 retval = kbinput - 96;
1351 else
1352 retval = kbinput;
1353
1354#ifdef DEBUG
1355 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1356#endif
1357
1358 return retval;
1359}
1360
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001361/* Put the output-formatted characters in output back into the default
1362 * keystroke buffer, so that they can be parsed and displayed as output
1363 * again. */
1364void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001365{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001366 int *input;
1367 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001368
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001369 if (output_len == 0)
1370 return;
1371
1372 input = (int *)nmalloc(output_len * sizeof(int));
1373 for (i = 0; i < output_len; i++)
1374 input[i] = (int)output[i];
1375 unget_input(input, output_len);
1376 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001377}
1378
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001379/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001380 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1381int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1382{
1383 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001384
1385 /* Turn off flow control characters if necessary so that we can type
1386 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001387 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001388 if (ISSET(PRESERVE))
1389 disable_flow_control();
1390 keypad(win, FALSE);
1391
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001392 /* Read in a stream of characters and interpret it if possible. */
1393 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001394
1395 /* Turn flow control characters back on if necessary and turn the
1396 * keypad back on now that we're done. */
1397 if (ISSET(PRESERVE))
1398 enable_flow_control();
1399 keypad(win, TRUE);
1400
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001401 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001402}
1403
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001404/* Read in a stream of all available characters, and return the length
1405 * of the string in kbinput_len. Translate the first few characters of
1406 * the input into the corresponding word value if possible. After that,
1407 * leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001408int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001409{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001410 int *kbinput, word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001411
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001412 /* Read in the first keystroke. */
1413 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001414
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001415 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001416 word = get_word_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001417#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001418 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001419#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001420 );
1421
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001422 /* If the first keystroke isn't a hexadecimal digit, put back the
1423 * first keystroke. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001424 if (word != ERR)
1425 unget_input(kbinput, 1);
1426 /* Otherwise, read in keystrokes until we have a complete word
1427 * sequence, and put back the corresponding word value. */
1428 else {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001429 char *word_mb = charalloc(mb_cur_max());
1430 int word_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001431
1432 while (word == ERR) {
1433 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001434
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001435 word = get_word_kbinput(*kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001436#ifndef NANO_SMALL
1437 , FALSE
1438#endif
1439 );
1440 }
1441
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001442 /* Put back the multibyte equivalent of the word value. */
1443 word_mb = make_mbchar(word, word_mb, &word_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001444
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001445 seq = (int *)nmalloc(word_mb_len * sizeof(int));
1446
1447 for (i = 0; i < word_mb_len; i++)
1448 seq[i] = (unsigned char)word_mb[i];
1449
1450 unget_input(seq, word_mb_len);
1451
1452 free(seq);
1453 free(word_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001454 }
1455
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001456 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001457 * result. */
1458 *kbinput_len = get_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001459 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001460
1461 return retval;
1462}
1463
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001464#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001465/* Check for a mouse event, and if one's taken place, save the
1466 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001467 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1468 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001469 * place on it, figure out which shortcut was clicked and put back the
1470 * equivalent keystroke(s). Return FALSE if no keystrokes were
1471 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001472 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001473bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001474{
1475 MEVENT mevent;
1476
1477 *mouse_x = -1;
1478 *mouse_y = -1;
1479
1480 /* First, get the actual mouse event. */
1481 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001482 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001483
1484 /* Save the screen coordinates where the mouse event took place. */
1485 *mouse_x = mevent.x;
1486 *mouse_y = mevent.y;
1487
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001488 /* If we're allowing shortcuts, the current shortcut list is being
1489 * displayed on the last two lines of the screen, and the mouse
1490 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001491 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001492 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1493 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001494 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001495 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001496 /* The number of shortcuts in the current shortcut list. */
1497 const shortcut *s = currshortcut;
1498 /* The actual shortcut we clicked on, starting at the first
1499 * one in the current shortcut list. */
1500
1501 /* Get the shortcut lists' length. */
1502 if (currshortcut == main_list)
1503 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001504 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001505 currslen = length_of_list(currshortcut);
1506
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001507 /* We don't show any more shortcuts than the main list
1508 * does. */
1509 if (currslen > MAIN_VISIBLE)
1510 currslen = MAIN_VISIBLE;
1511 }
1512
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001513 /* Calculate the width of each shortcut in the list (it's the
1514 * same for all of them). */
1515 if (currslen < 2)
1516 i = COLS / 6;
1517 else
1518 i = COLS / ((currslen / 2) + (currslen % 2));
1519
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001520 /* Calculate the y-coordinate relative to the beginning of
1521 * bottomwin. */
1522 j = *mouse_y - ((2 - no_more_space()) + 1) - editwinrows;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001523
1524 /* If we're on the statusbar, beyond the end of the shortcut
1525 * list, or beyond the end of a shortcut on the right side of
1526 * the screen, don't do anything. */
1527 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001528 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001529 j = (*mouse_x / i) * 2 + j;
1530 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001531 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001532
1533 /* Go through the shortcut list to determine which shortcut was
1534 * clicked. */
1535 for (; j > 0; j--)
1536 s = s->next;
1537
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001538 /* And put back the equivalent key. Assume that each shortcut
1539 * has, at the very least, an equivalent control key, an
1540 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001541 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001542 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001543 return TRUE;
1544 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001545 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001546 return TRUE;
1547 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001548 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001549 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001550}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001551#endif /* !DISABLE_MOUSE */
1552
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001553const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001554 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001555{
1556 const shortcut *s = s_list;
1557 size_t slen = length_of_list(s_list);
1558
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001559#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001560 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 +00001561#endif
1562
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001563 /* Check for shortcuts. */
1564 for (; slen > 0; slen--) {
1565 /* We've found a shortcut if:
1566 *
1567 * 1. The key exists.
1568 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001569 * 3. meta_key is TRUE and the key is the primary or
1570 * miscellaneous meta sequence in the shortcut list.
1571 * 4. func_key is TRUE and the key is a function key in the
1572 * shortcut list. */
1573
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001574 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1575 (*meta_key == TRUE && (*kbinput == s->metaval ||
1576 *kbinput == s->miscval)) || (*func_key == TRUE &&
1577 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001578 break;
1579 }
1580
1581 s = s->next;
1582 }
1583
1584 /* Translate the shortcut to either its control key or its meta key
1585 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001586 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001587 if (slen > 0) {
1588 if (s->ctrlval != NANO_NO_KEY) {
1589 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001590 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001591 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001592 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001593 } else if (s->metaval != NANO_NO_KEY) {
1594 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001595 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001596 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001597 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001598 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001599 }
1600
1601 return NULL;
1602}
1603
1604#ifndef NANO_SMALL
1605const toggle *get_toggle(int kbinput, bool meta_key)
1606{
1607 const toggle *t = toggles;
1608
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001609#ifdef DEBUG
1610 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1611#endif
1612
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001613 /* Check for toggles. */
1614 for (; t != NULL; t = t->next) {
1615 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001616 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001617 if (meta_key && kbinput == t->val)
1618 break;
1619 }
1620
1621 return t;
1622}
1623#endif /* !NANO_SMALL */
1624
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001625int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001626 bool *ran_func, bool *finished, bool allow_funcs)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001627{
1628 int input;
1629 /* The character we read in. */
1630 static int *kbinput = NULL;
1631 /* The input buffer. */
1632 static size_t kbinput_len = 0;
1633 /* The length of the input buffer. */
1634 const shortcut *s;
1635 bool have_shortcut;
1636
1637 *s_or_t = FALSE;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001638 *ran_func = FALSE;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001639 *finished = FALSE;
1640
1641 /* Read in a character. */
1642 input = get_kbinput(bottomwin, meta_key, func_key);
1643
1644#ifndef DISABLE_MOUSE
1645 /* If we got a mouse click and it was on a shortcut, read in the
1646 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001647 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001648 if (do_mouse())
1649 input = get_kbinput(bottomwin, meta_key, func_key);
1650 else
1651 input = ERR;
1652 }
1653#endif
1654
1655 /* Check for a shortcut in the current list. */
1656 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1657
1658 /* If we got a shortcut from the current list, or a "universal"
1659 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1660 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1661 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1662 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1663 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001664 input == NANO_CUT_KEY ||
1665#ifndef NANO_SMALL
1666 input == NANO_NEXTWORD_KEY ||
1667#endif
1668 (*meta_key == TRUE && (
1669#ifndef NANO_SMALL
1670 input == NANO_PREVWORD_KEY ||
1671#endif
1672 input == NANO_VERBATIM_KEY)));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001673
1674 /* Set s_or_t to TRUE if we got a shortcut. */
1675 *s_or_t = have_shortcut;
1676
1677 if (allow_funcs) {
1678 if (input != ERR && *s_or_t == FALSE && !is_cntrl_char(input)) {
1679 /* If we're using restricted mode, the filename isn't blank,
1680 * and we're at the "Write File" prompt, disable text
1681 * input. */
1682 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1683 currshortcut != writefile_list) {
1684 kbinput_len++;
1685 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1686 sizeof(int));
1687 kbinput[kbinput_len - 1] = input;
1688 }
1689 }
1690
1691 /* If we got a shortcut, or if there aren't any other characters
1692 * waiting after the one we read in, we need to display all the
1693 * characters in the input buffer if it isn't empty. */
1694 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1695 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001696
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001697 /* Display all the characters in the input buffer at
1698 * once. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001699 char *output = charalloc(kbinput_len + 1);
1700 size_t i;
1701 bool got_enter;
1702 /* Whether we got the Enter key. */
1703
1704 for (i = 0; i < kbinput_len; i++)
1705 output[i] = (char)kbinput[i];
1706 output[i] = '\0';
1707
1708 do_statusbar_output(output, kbinput_len, &got_enter);
1709
1710 free(output);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001711
1712 /* Empty the input buffer. */
1713 kbinput_len = 0;
1714 free(kbinput);
1715 kbinput = NULL;
1716 }
1717 }
1718
1719 if (have_shortcut) {
1720 switch (input) {
1721 /* Handle the "universal" statusbar prompt shortcuts. */
1722 case NANO_REFRESH_KEY:
1723 total_refresh();
1724 break;
1725 case NANO_HOME_KEY:
1726 do_statusbar_home();
1727 break;
1728 case NANO_END_KEY:
1729 do_statusbar_end();
1730 break;
1731 case NANO_FORWARD_KEY:
1732 do_statusbar_right();
1733 break;
1734 case NANO_BACK_KEY:
1735 do_statusbar_left();
1736 break;
1737 case NANO_BACKSPACE_KEY:
1738 /* If we're using restricted mode, the filename
1739 * isn't blank, and we're at the "Write File"
1740 * prompt, disable Backspace. */
1741 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1742 currshortcut != writefile_list)
1743 do_statusbar_backspace();
1744 break;
1745 case NANO_DELETE_KEY:
1746 /* If we're using restricted mode, the filename
1747 * isn't blank, and we're at the "Write File"
1748 * prompt, disable Delete. */
1749 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1750 currshortcut != writefile_list)
1751 do_statusbar_delete();
1752 break;
1753 case NANO_CUT_KEY:
1754 /* If we're using restricted mode, the filename
1755 * isn't blank, and we're at the "Write File"
1756 * prompt, disable Cut. */
1757 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1758 currshortcut != writefile_list)
1759 do_statusbar_cut_text();
1760 break;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001761#ifndef NANO_SMALL
1762 case NANO_NEXTWORD_KEY:
1763 do_statusbar_next_word();
1764 break;
1765 case NANO_PREVWORD_KEY:
1766 if (*meta_key == TRUE)
1767 do_statusbar_prev_word();
1768 break;
1769#endif
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001770 case NANO_VERBATIM_KEY:
1771 if (*meta_key == TRUE) {
1772 /* If we're using restricted mode, the filename
1773 * isn't blank, and we're at the "Write File"
1774 * prompt, disable verbatim input. */
1775 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001776 currshortcut != writefile_list) {
1777 bool got_enter;
1778 /* Whether we got the Enter key. */
1779
1780 do_statusbar_verbatim_input(&got_enter);
1781
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001782 /* If we got the Enter key, set input to the
1783 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001784 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001785 if (got_enter) {
1786 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001787 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001788 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001789 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001790 break;
1791 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001792 /* Handle the normal statusbar prompt shortcuts, setting
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001793 * ran_func to TRUE if we try to run their associated
1794 * functions and setting finished to TRUE to indicate
1795 * that we're done after trying to run their associated
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001796 * functions. */
1797 default:
1798 if (s->func != NULL) {
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001799 *ran_func = TRUE;
1800 if (!ISSET(VIEW_MODE) || s->viewok)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001801 s->func();
1802 }
1803 *finished = TRUE;
1804 }
1805 }
1806 }
1807
1808 return input;
1809}
1810
1811#ifndef DISABLE_MOUSE
1812bool do_statusbar_mouse(void)
1813{
1814 /* FIXME: If we clicked on a location in the statusbar, the cursor
1815 * should move to the location we clicked on. This functionality
1816 * should be in this function. */
1817 int mouse_x, mouse_y;
1818 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1819}
1820#endif
1821
1822void do_statusbar_home(void)
1823{
1824#ifndef NANO_SMALL
1825 if (ISSET(SMART_HOME)) {
1826 size_t statusbar_x_save = statusbar_x;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001827
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001828 statusbar_x = indent_length(answer);
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001829
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001830 if (statusbar_x == statusbar_x_save ||
1831 statusbar_x == statusbar_xend)
1832 statusbar_x = 0;
1833 } else
1834#endif
1835 statusbar_x = 0;
1836}
1837
1838void do_statusbar_end(void)
1839{
1840 statusbar_x = statusbar_xend;
1841}
1842
1843void do_statusbar_right(void)
1844{
1845 if (statusbar_x < statusbar_xend)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001846 statusbar_x = move_mbright(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001847}
1848
1849void do_statusbar_left(void)
1850{
1851 if (statusbar_x > 0)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001852 statusbar_x = move_mbleft(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001853}
1854
1855void do_statusbar_backspace(void)
1856{
1857 if (statusbar_x > 0) {
1858 do_statusbar_left();
1859 do_statusbar_delete();
1860 }
1861}
1862
1863void do_statusbar_delete(void)
1864{
1865 if (statusbar_x < statusbar_xend) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001866 int char_buf_len = parse_mbchar(answer + statusbar_x, NULL,
1867 NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001868
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001869 charmove(answer + statusbar_x, answer + statusbar_x +
1870 char_buf_len, statusbar_xend - statusbar_x -
1871 char_buf_len + 1);
1872 statusbar_xend -= char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001873 }
1874}
1875
1876void do_statusbar_cut_text(void)
1877{
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001878 if (ISSET(CUT_TO_END)) {
1879 null_at(&answer, statusbar_x);
1880 statusbar_xend = statusbar_x;
1881 } else {
1882 null_at(&answer, 0);
1883 statusbar_x = 0;
1884 statusbar_xend = 0;
1885 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001886}
1887
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001888#ifndef NANO_SMALL
1889void do_statusbar_next_word(void)
1890{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001891 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001892 int char_mb_len;
1893
1894 assert(answer != NULL);
1895
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001896 char_mb = charalloc(mb_cur_max());
1897
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001898 /* Move forward until we find the character after the last letter of
1899 * the current word. */
1900 while (statusbar_x < statusbar_xend) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001901 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1902 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001903
1904 /* If we've found it, stop moving forward through the current
1905 * line. */
1906 if (!is_alnum_mbchar(char_mb))
1907 break;
1908
1909 statusbar_x += char_mb_len;
1910 }
1911
1912 /* Move forward until we find the first letter of the next word. */
1913 if (statusbar_x < statusbar_xend)
1914 current_x += char_mb_len;
1915
1916 while (statusbar_x < statusbar_xend) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001917 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1918 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001919
1920 /* If we've found it, stop moving forward through the current
1921 * line. */
1922 if (is_alnum_mbchar(char_mb))
1923 break;
1924
1925 statusbar_x += char_mb_len;
1926 }
1927
1928 free(char_mb);
1929}
1930
1931void do_statusbar_prev_word(void)
1932{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001933 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001934 int char_mb_len;
1935 bool begin_line = FALSE;
1936
1937 assert(answer != NULL);
1938
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001939 char_mb = charalloc(mb_cur_max());
1940
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001941 /* Move backward until we find the character before the first letter
1942 * of the current word. */
1943 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001944 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1945 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001946
1947 /* If we've found it, stop moving backward through the current
1948 * line. */
1949 if (!is_alnum_mbchar(char_mb))
1950 break;
1951
1952 if (statusbar_x == 0)
1953 begin_line = TRUE;
1954 else
1955 statusbar_x = move_mbleft(answer, statusbar_x);
1956 }
1957
1958 /* Move backward until we find the last letter of the previous
1959 * word. */
1960 if (statusbar_x == 0)
1961 begin_line = TRUE;
1962 else
1963 statusbar_x = move_mbleft(answer, statusbar_x);
1964
1965 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001966 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1967 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001968
1969 /* If we've found it, stop moving backward through the current
1970 * line. */
1971 if (is_alnum_mbchar(char_mb))
1972 break;
1973
1974 if (statusbar_x == 0)
1975 begin_line = TRUE;
1976 else
1977 statusbar_x = move_mbleft(answer, statusbar_x);
1978 }
1979
1980 /* If we've found it, move backward until we find the character
1981 * before the first letter of the previous word. */
1982 if (!begin_line) {
1983 if (statusbar_x == 0)
1984 begin_line = TRUE;
1985 else
1986 statusbar_x = move_mbleft(answer, statusbar_x);
1987
1988 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001989 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
1990 NULL, NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001991
1992 /* If we've found it, stop moving backward through the
1993 * current line. */
1994 if (!is_alnum_mbchar(char_mb))
1995 break;
1996
1997 if (statusbar_x == 0)
1998 begin_line = TRUE;
1999 else
2000 statusbar_x = move_mbleft(answer, statusbar_x);
2001 }
2002
2003 /* If we've found it, move forward to the first letter of the
2004 * previous word. */
2005 if (!begin_line)
2006 statusbar_x += char_mb_len;
2007 }
2008
2009 free(char_mb);
2010}
2011#endif
2012
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002013void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002014{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002015 int *kbinput;
2016 size_t kbinput_len, i;
2017 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002018
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002019 *got_enter = FALSE;
2020
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002021 /* Read in all the verbatim characters. */
2022 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
2023
2024 /* Display all the verbatim characters at once. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002025 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002026
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002027 for (i = 0; i < kbinput_len; i++)
2028 output[i] = (char)kbinput[i];
2029 output[i] = '\0';
2030
2031 do_statusbar_output(output, kbinput_len, got_enter);
2032
2033 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002034}
2035
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002036void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002037 *got_enter)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002038{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002039 size_t i = 0;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002040
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002041 char *char_buf = charalloc(mb_cur_max());
2042 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002043
2044 assert(answer != NULL);
2045
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002046 *got_enter = FALSE;
2047
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002048 while (i < output_len) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002049 /* Null to newline, if needed. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002050 if (output[i] == '\0')
2051 output[i] = '\n';
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002052 /* Newline to Enter, if needed. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002053 else if (output[i] == '\n') {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002054 /* Set got_enter to TRUE to indicate that we got the Enter
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002055 * key, put back the rest of the characters in output so
2056 * that they can be parsed and output again, and get out. */
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002057 *got_enter = TRUE;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002058 unparse_kbinput(output + i, output_len - i);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002059 return;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002060 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002061
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002062 /* Interpret the next multibyte character. If it's an invalid
2063 * multibyte character, interpret it as though it's a byte
2064 * character. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002065 char_buf_len = parse_mbchar(output + i, char_buf, NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002066
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002067 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002068
2069 /* More dangerousness fun =) */
David Lawrence Ramsey49ff08b2005-01-14 04:13:45 +00002070 answer = charealloc(answer, statusbar_xend +
2071 (char_buf_len * 2));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002072
2073 assert(statusbar_x <= statusbar_xend);
2074
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002075 charmove(&answer[statusbar_x + char_buf_len],
2076 &answer[statusbar_x], statusbar_xend - statusbar_x +
2077 char_buf_len);
2078 charcpy(&answer[statusbar_x], char_buf, char_buf_len);
2079 statusbar_xend += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002080
2081 do_statusbar_right();
2082 }
2083
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002084 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002085}
2086
Chris Allegretta6df90f52002-07-19 01:08:59 +00002087/* Return the placewewant associated with current_x. That is, xplustabs
2088 * is the zero-based column position of the cursor. Value is no smaller
2089 * than current_x. */
2090size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002091{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002092 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002093}
2094
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002095/* actual_x() gives the index in str of the character displayed at
2096 * column xplus. That is, actual_x() is the largest value such that
2097 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2098size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002099{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002100 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002101 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002102 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002103 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002104
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002105 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002106
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002107 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002108 int str_len = parse_mbchar(str, NULL, NULL, &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002109
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002110 if (length > xplus)
2111 break;
2112
2113 i += str_len;
2114 str += str_len;
2115 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002116
Chris Allegretta6df90f52002-07-19 01:08:59 +00002117 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002118}
2119
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002120/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002121 * columns wide are the first size characters of str? */
2122size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002123{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002124 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002125 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002126
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002127 if (size == 0)
2128 return 0;
2129
2130 assert(str != NULL);
2131
2132 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002133 int str_len = parse_mbchar(str, NULL, NULL, &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002134
2135 str += str_len;
2136
2137 if (size <= str_len)
2138 break;
2139
2140 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002141 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002142
Chris Allegretta6df90f52002-07-19 01:08:59 +00002143 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002144}
2145
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002146/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002147size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002148{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002149 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002150}
2151
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002152void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002153{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002154 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002155}
2156
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002157void blank_topbar(void)
2158{
2159 if (!ISSET(MORE_SPACE))
2160 mvwaddstr(topwin, 1, 0, hblank);
2161}
2162
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002163void blank_edit(void)
2164{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002165 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002166 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002167 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002168}
2169
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002170void blank_statusbar(void)
2171{
2172 mvwaddstr(bottomwin, 0, 0, hblank);
2173}
2174
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002175void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002176{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002177 if (statusblank > 1)
2178 statusblank--;
2179 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
2180 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002181 blank_statusbar();
2182 wnoutrefresh(bottomwin);
2183 reset_cursor();
2184 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002185 }
2186}
2187
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002188void blank_bottombars(void)
2189{
2190 if (!ISSET(NO_HELP)) {
2191 mvwaddstr(bottomwin, 1, 0, hblank);
2192 mvwaddstr(bottomwin, 2, 0, hblank);
2193 }
2194}
2195
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002196/* Convert buf into a string that can be displayed on screen. The
2197 * caller wants to display buf starting with column start_col, and
2198 * extending for at most len columns. start_col is zero-based. len is
2199 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002200 * string is dynamically allocated, and should be freed. If dollars is
2201 * TRUE, the caller might put "$" at the beginning or end of the line if
2202 * it's too long. */
2203char *display_string(const char *buf, size_t start_col, size_t len, bool
2204 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002205{
2206 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002207 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002208 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002209 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002210 size_t alloc_len;
2211 /* The length of memory allocated for converted. */
2212 char *converted;
2213 /* The string we return. */
2214 size_t index;
2215 /* Current position in converted. */
2216
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002217 char *buf_mb = charalloc(mb_cur_max());
2218 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002219 bool bad_char;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002220
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002221 /* If dollars is TRUE, make room for the "$" at the end of the
2222 * line. */
2223 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2224 len--;
2225
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002226 if (len == 0)
2227 return mallocstrcpy(NULL, "");
2228
2229 start_index = actual_x(buf, start_col);
2230 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002231
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002232 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002233
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002234 /* Allocate enough space for the entire line. It should contain
2235 * (len + 2) multibyte characters at most. */
2236 alloc_len = mb_cur_max() * (len + 2);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002237
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002238 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002239 index = 0;
2240
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002241 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002242 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002243 /* We don't display all of buf[start_index] since it starts to
2244 * the left of the screen. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002245 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL,
2246 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002247
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002248 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002249 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002250 char *ctrl_buf_mb = charalloc(mb_cur_max());
2251 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002252
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002253 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2254 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002255
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002256 for (i = 0; i < ctrl_buf_mb_len; i++)
2257 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002258
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002259 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002260
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002261 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002262
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002263 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002264 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002265 }
2266#ifdef NANO_WIDE
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002267 else if (mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002268 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002269 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002270
2271 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002272 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002273#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002274 }
2275
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002276 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseybc149412005-02-11 20:23:00 +00002277 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, &bad_char,
2278 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002279
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002280 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002281 converted[index++] =
2282#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2283 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
2284#endif
2285 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002286 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002287 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002288 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002289 start_col++;
2290 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002291 /* If buf contains a control character, interpret it. If it
2292 * contains an invalid multibyte control character, interpret
2293 * that character as though it's a normal control character. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002294 } else if (is_cntrl_mbchar(buf_mb)) {
2295 char *ctrl_buf_mb = charalloc(mb_cur_max());
2296 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002297
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002298 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002299 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002300
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002301 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2302 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002303
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002304 for (i = 0; i < ctrl_buf_mb_len; i++)
2305 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002306
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002307 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002308
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002309 free(ctrl_buf_mb);
2310 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002311 converted[index++] =
2312#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2313 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
2314#endif
2315 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002316 start_col++;
2317 } else {
2318 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002319
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002320#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002321 /* If buf contains an invalid multibyte non-control
2322 * character, interpret that character as though it's a
2323 * normal non-control character. */
2324 if (!ISSET(NO_UTF8) && bad_char) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002325 char *bad_buf_mb = charalloc(mb_cur_max());
2326 int bad_buf_mb_len;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002327
David Lawrence Ramsey4c6956b2005-01-12 04:32:43 +00002328 bad_buf_mb = make_mbchar((unsigned char)*buf_mb,
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002329 bad_buf_mb, &bad_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002330
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002331 for (i = 0; i < bad_buf_mb_len; i++)
2332 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002333
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002334 start_col += mbwidth(bad_buf_mb);
2335
2336 free(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002337 } else {
2338#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002339 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002340 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002341
2342 start_col += mbwidth(buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002343#ifdef NANO_WIDE
2344 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002345#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002346 }
2347
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002348 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002349 }
2350
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002351 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002352 converted[index] = '\0';
2353
2354 /* Make sure converted takes up no more than len columns. */
2355 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002356 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002357
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002358 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002359}
2360
Chris Allegretta7662c862003-01-13 01:35:15 +00002361/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002362 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002363 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002364 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002365 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002366void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002367{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002368 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002369 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002370
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002371 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002372
Chris Allegrettab3655b42001-10-22 03:15:31 +00002373 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002374 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002375
Chris Allegretta6df90f52002-07-19 01:08:59 +00002376 mvwaddstr(bottomwin, 0, 0, buf);
2377 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002378
2379 if (COLS > 1)
2380 waddch(bottomwin, x_real < wid ? ' ' : '$');
2381 if (COLS > 2) {
2382 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002383 char *expanded = display_string(inputbuf, page_start, wid,
2384 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002385
2386 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002387 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002388
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002389 waddstr(bottomwin, expanded);
2390 free(expanded);
2391 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2392 } else
2393 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002394 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002395}
2396
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002397/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002398 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002399int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002400#ifndef NANO_SMALL
2401 historyheadtype *history_list,
2402#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002403 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002404#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002405 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002406#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002407 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002408{
2409 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002410 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002411 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002412 /* used by input_tab() */
Chris Allegretta598106e2002-01-19 01:59:37 +00002413
Chris Allegretta5beed502003-01-05 20:41:21 +00002414#ifndef NANO_SMALL
2415 /* for history */
2416 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00002417 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00002418 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002419 int last_kbinput = 0;
2420
2421 /* This variable is used in the search history code. use_cb == 0
2422 means that we're using the existing history and ignoring
2423 currentbuf. use_cb == 1 means that the entry in answer should be
2424 moved to currentbuf or restored from currentbuf to answer.
2425 use_cb == 2 means that the entry in currentbuf should be moved to
2426 answer or restored from answer to currentbuf. */
2427 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002428#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002429 statusbar_xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002430
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002431 /* Only put statusbar_x at the end of the string if it's
2432 * uninitialized, if it would be past the end of the string as it
2433 * is, or if resetstatuspos is TRUE. Otherwise, leave it alone.
2434 * This is so the cursor position stays at the same place if a
2435 * prompt-changing toggle is pressed. */
2436 if (statusbar_x == (size_t)-1 || statusbar_x > statusbar_xend ||
2437 resetstatuspos)
2438 statusbar_x = statusbar_xend;
Chris Allegretta09fc4302003-01-16 22:16:38 +00002439
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002440 answer = charealloc(answer, statusbar_xend + 1);
2441 if (statusbar_xend > 0)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002442 strcpy(answer, def);
2443 else
2444 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002445
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002446 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002447
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002448 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00002449
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002450 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002451
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002452 /* Refresh the edit window before getting input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002453 wnoutrefresh(edit);
2454 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002455
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002456 /* If we're using restricted mode, we aren't allowed to change the
2457 * name of a file once it has one because that would allow writing
2458 * to files not specified on the command line. In this case,
2459 * disable all keys that would change the text if the filename isn't
2460 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002461 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002462 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002463 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002464
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002465 /* If we have a shortcut with an associated function, break out
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002466 * if we're finished after running or trying to run the
2467 * function. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002468 if (finished)
2469 break;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002470
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002471 assert(statusbar_x <= statusbar_xend &&
2472 statusbar_xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002473
Chris Allegretta04d848e2000-11-05 17:54:41 +00002474 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002475 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00002476
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002477 switch (kbinput) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002478 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002479#ifndef NANO_SMALL
2480 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00002481 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002482 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002483 history_list->current = (historytype *)history_list;
2484 history_list->len = strlen(answer);
2485 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002486
Chris Allegretta7662c862003-01-13 01:35:15 +00002487 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002488 complete = get_history_completion(history_list, answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002489 statusbar_x = strlen(complete);
2490 statusbar_xend = statusbar_x;
Chris Allegretta5beed502003-01-05 20:41:21 +00002491 answer = mallocstrcpy(answer, complete);
2492 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002493 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002494#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002495 else
2496#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002497#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002498#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002499 if (allow_tabs) {
David Lawrence Ramsey65e6ecb2005-02-08 20:37:53 +00002500 answer = input_tab(answer, &statusbar_x, &tabbed, list);
David Lawrence Ramsey2724c882005-02-11 16:23:56 +00002501 statusbar_xend = strlen(answer);
Chris Allegretta5beed502003-01-05 20:41:21 +00002502 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002503 break;
David Lawrence Ramsey65e6ecb2005-02-08 20:37:53 +00002504#endif
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002505 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002506#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002507 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002508
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002509 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2510 isn't NULL, and currentbuf is different from answer,
2511 it means that we're scrolling up at the top of the
2512 search history, and we need to save the current
2513 answer in currentbuf; do this and reset use_cb to
2514 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002515 if (currentbuf == NULL || (use_cb == 1 &&
2516 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002517 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002518 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002519 }
2520
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002521 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2522 is different from answer, it means that we're
2523 scrolling up at the bottom of the search history, and
2524 we need to make the string in currentbuf the current
2525 answer; do this, blow away currentbuf since we don't
2526 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002527 if (currentbuf != NULL && use_cb == 2 &&
2528 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002529 answer = mallocstrcpy(answer, currentbuf);
2530 free(currentbuf);
2531 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002532 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002533 use_cb = 0;
2534
2535 /* else get older search from the history list and save
2536 it in answer; if there is no older search, blank out
2537 answer */
2538 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002539 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002540 statusbar_xend = strlen(history);
Chris Allegretta5beed502003-01-05 20:41:21 +00002541 } else {
2542 answer = mallocstrcpy(answer, "");
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002543 statusbar_xend = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002544 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002545 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002546 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002547#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002548 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002549 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002550#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002551 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002552
2553 /* get newer search from the history list and save it
2554 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002555 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002556 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002557 statusbar_xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002558
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002559 /* if there is no newer search, we're here */
2560
2561 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2562 that we're scrolling down at the bottom of the search
2563 history and we need to make the string in currentbuf
2564 the current answer; do this, blow away currentbuf
2565 since we don't need it anymore, and set use_cb to
2566 1 */
2567 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002568 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002569 free(currentbuf);
2570 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002571 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002572 use_cb = 1;
2573
2574 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2575 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002576 the search history and the current answer (if it's
2577 not blank) needs to be saved in currentbuf; do this,
2578 blank out answer (if necessary), and set use_cb to
2579 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002580 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002581 if (answer[0] != '\0') {
2582 currentbuf = mallocstrcpy(currentbuf, answer);
2583 answer = mallocstrcpy(answer, "");
2584 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002585 statusbar_xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002586 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002587 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002588 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002589 }
2590#endif
2591 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002592 }
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002593#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002594 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002595#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002596 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002597 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002598 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002599
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002600 /* We finished putting in an answer or ran a normal shortcut's
2601 * associated function, so reset statusbar_x. */
2602 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
2603 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002604 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002605
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002606 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002607}
2608
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002609/* Ask a question on the statusbar. Answer will be stored in answer
2610 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2611 * otherwise, the valid shortcut key caught. def is any editable text
2612 * we want to put up by default.
2613 *
2614 * New arg tabs tells whether or not to allow tab completion. */
2615int statusq(bool allow_tabs, const shortcut *s, const char *def,
2616#ifndef NANO_SMALL
2617 historyheadtype *which_history,
2618#endif
2619 const char *msg, ...)
2620{
2621 va_list ap;
2622 char *foo = charalloc(COLS - 3);
2623 int ret;
2624#ifndef DISABLE_TABCOMP
2625 bool list = FALSE;
2626#endif
2627
2628 bottombars(s);
2629
2630 va_start(ap, msg);
2631 vsnprintf(foo, COLS - 4, msg, ap);
2632 va_end(ap);
2633 foo[COLS - 4] = '\0';
2634
2635 ret = nanogetstr(allow_tabs, foo, def,
2636#ifndef NANO_SMALL
2637 which_history,
2638#endif
2639 s
2640#ifndef DISABLE_TABCOMP
2641 , &list
2642#endif
2643 );
2644 free(foo);
2645 resetstatuspos = FALSE;
2646
2647 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002648 case NANO_CANCEL_KEY:
2649 ret = -1;
2650 resetstatuspos = TRUE;
2651 break;
2652 case NANO_ENTER_KEY:
2653 ret = (answer[0] == '\0') ? -2 : 0;
2654 resetstatuspos = TRUE;
2655 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002656 }
2657 blank_statusbar();
2658
2659#ifdef DEBUG
2660 fprintf(stderr, "I got \"%s\"\n", answer);
2661#endif
2662
2663#ifndef DISABLE_TABCOMP
2664 /* if we've done tab completion, there might be a list of
2665 filename matches on the edit window at this point; make sure
2666 they're cleared off. */
2667 if (list)
2668 edit_refresh();
2669#endif
2670
2671 return ret;
2672}
2673
2674void statusq_abort(void)
2675{
2676 resetstatuspos = TRUE;
2677}
2678
Chris Allegrettaf717f982003-02-13 22:25:01 +00002679void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002680{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002681 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002682 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002683 size_t verlen = strlenpt(VERMSG) + 1;
2684 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002685 const char *prefix;
2686 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2687 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002688 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002689 const char *state;
2690 /* "Modified", "View", or spaces the length of "Modified".
2691 * Tells the state of this buffer. */
2692 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002693 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002694 char *exppath = NULL;
2695 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002696 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002697 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002698 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002699 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002700
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002701 assert(path != NULL || filename != NULL);
2702 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002703
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002704 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002705
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002706 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002707
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002708 if (COLS <= 5 || COLS - 5 < verlen)
2709 space = 0;
2710 else {
2711 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002712 /* Reserve 2/3 of the screen plus one column for after the
2713 * version message. */
2714 if (space < COLS - (COLS / 3) + 1)
2715 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002716 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002717
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002718 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002719 /* The version message should only take up 1/3 of the screen
2720 * minus one column. */
2721 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002722 waddstr(topwin, " ");
2723 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002724
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002725 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002726 state = _("Modified");
2727 else if (path == NULL && ISSET(VIEW_MODE))
2728 state = _("View");
2729 else {
2730 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002731 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002732 state = &hblank[COLS - statelen];
2733 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002734 statelen = strnlenpt(state, COLS);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002735 /* We need a space before state. */
2736 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2737 statelen++;
2738
2739 assert(space >= 0);
2740 if (space == 0 || statelen >= space)
2741 goto the_end;
2742
2743#ifndef DISABLE_BROWSER
2744 if (path != NULL)
2745 prefix = _("DIR:");
2746 else
2747#endif
2748 if (filename[0] == '\0') {
2749 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002750 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002751 } else
2752 prefix = _("File:");
2753 assert(statelen < space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002754 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002755 /* If newfie is FALSE, we need a space after prefix. */
2756 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002757 prefixlen++;
2758
2759 if (path == NULL)
2760 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002761 if (space >= prefixlen + statelen)
2762 space -= prefixlen + statelen;
2763 else
2764 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002765 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002766 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002767 size_t lenpt = strlenpt(path), start_col;
2768
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002769 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002770
2771 if (dots) {
2772 start_col = lenpt - space + 3;
2773 space -= 3;
2774 } else
2775 start_col = 0;
2776
2777 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002778 }
2779
2780 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002781 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2782 /* The length of the expanded filename. */
2783
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002784 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002785 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002786 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002787 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002788 assert(strlenpt(prefix) + 1 == prefixlen);
2789
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002790 waddch(topwin, ' ');
2791 waddstr(topwin, exppath);
2792 }
2793 } else {
2794 /* We will say something like "File: ...ename". */
2795 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002796 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002797 goto the_end;
2798 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002799 waddnstr(topwin, "...", space + 3);
2800 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002801 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002802 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002803 }
2804
2805 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002806 free(exppath);
2807
2808 if (COLS <= 1 || statelen >= COLS - 1)
2809 mvwaddnstr(topwin, 0, 0, state, COLS);
2810 else {
2811 assert(COLS - statelen - 2 >= 0);
2812 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2813 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2814 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002815
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002816 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002817
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002818 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002819 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002820 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002821}
2822
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002823/* If modified is not already set, set it and update titlebar. */
2824void set_modified(void)
2825{
2826 if (!ISSET(MODIFIED)) {
2827 SET(MODIFIED);
2828 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002829 }
2830}
2831
2832void statusbar(const char *msg, ...)
2833{
2834 va_list ap;
2835
2836 va_start(ap, msg);
2837
2838 /* Curses mode is turned off. If we use wmove() now, it will muck
2839 * up the terminal settings. So we just use vfprintf(). */
2840 if (curses_ended) {
2841 vfprintf(stderr, msg, ap);
2842 va_end(ap);
2843 return;
2844 }
2845
2846 /* Blank out the line. */
2847 blank_statusbar();
2848
2849 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002850 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002851 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002852#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002853 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002854
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002855 UNSET(WHITESPACE_DISPLAY);
2856#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002857 bar = charalloc(mb_cur_max() * (COLS - 3));
2858 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002859 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002860 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002861#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2862 if (old_whitespace)
2863 SET(WHITESPACE_DISPLAY);
2864#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002865 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002866 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002867 start_x = (COLS - foo_len - 4) / 2;
2868
2869 wmove(bottomwin, 0, start_x);
2870 wattron(bottomwin, A_REVERSE);
2871
2872 waddstr(bottomwin, "[ ");
2873 waddstr(bottomwin, foo);
2874 free(foo);
2875 waddstr(bottomwin, " ]");
2876 wattroff(bottomwin, A_REVERSE);
2877 wnoutrefresh(bottomwin);
2878 reset_cursor();
2879 wrefresh(edit);
2880 /* Leave the cursor at its position in the edit window, not
2881 * in the statusbar. */
2882 }
2883
2884 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002885 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002886}
2887
Chris Allegretta6232d662002-05-12 19:52:15 +00002888void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002889{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002890 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002891
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002892 if (ISSET(NO_HELP))
2893 return;
2894
Chris Allegretta6232d662002-05-12 19:52:15 +00002895 if (s == main_list) {
2896 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002897 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002898 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002899 slen = length_of_list(s);
2900
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002901 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002902 if (slen > MAIN_VISIBLE)
2903 slen = MAIN_VISIBLE;
2904 }
2905
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002906 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002907 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002908 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002909
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002910 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002911
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002912 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002913 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002914
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002915 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002916#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002917 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002918 keystr = _("Up");
2919 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002920#endif
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00002921 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002922
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002923 if (s->ctrlval == NANO_CONTROL_SPACE)
2924 strcpy(foo, "^ ");
2925 else if (s->ctrlval == NANO_CONTROL_8)
2926 strcpy(foo, "^?");
2927 /* Normal values. Assume that the shortcut has an
2928 * equivalent control key, meta key sequence, or both. */
2929 else if (s->ctrlval != NANO_NO_KEY)
2930 sprintf(foo, "^%c", s->ctrlval + 64);
2931 else if (s->metaval != NANO_NO_KEY)
2932 sprintf(foo, "M-%c", toupper(s->metaval));
2933
2934 keystr = foo;
2935#ifndef NANO_SMALL
2936 }
2937#endif
2938
2939 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002940 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002941 }
2942
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002943 wnoutrefresh(bottomwin);
2944 reset_cursor();
2945 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002946}
2947
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002948/* Write a shortcut key to the help area at the bottom of the window.
2949 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2950 * to write at most len characters, even if len is very small and
2951 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2952 * the whole string! We do not bother padding the entry with blanks. */
2953void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002954{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002955 size_t keystroke_len = strlenpt(keystroke) + 1;
2956
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002957 assert(keystroke != NULL && desc != NULL);
2958
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002959 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002960 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002961 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002962
2963 if (len > keystroke_len)
2964 len -= keystroke_len;
2965 else
2966 len = 0;
2967
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002968 if (len > 0) {
2969 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002970 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002971 }
2972}
2973
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002974/* And so start the display update routines. */
2975
2976#ifndef NDEBUG
2977int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002978{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002979 int check_line = 0;
2980 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002981
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002982 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
2983 check_line++;
2984 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002985}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002986#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00002987
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002988/* nano scrolls horizontally within a line in chunks. This function
2989 * returns the column number of the first character displayed in the
2990 * window when the cursor is at the given column. Note that
2991 * 0 <= column - get_page_start(column) < COLS. */
2992size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002993{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002994 assert(COLS > 0);
2995 if (column == 0 || column < COLS - 1)
2996 return 0;
2997 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002998 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002999 else if (COLS > 2)
3000 return column - (COLS - 2);
3001 else
3002 return column - (COLS - 1);
3003 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003004}
3005
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003006/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003007 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003008void reset_cursor(void)
3009{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003010 /* If we haven't opened any files yet, put the cursor in the top
3011 * left corner of the edit window and get out. */
3012 if (edittop == NULL || current == NULL) {
3013 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003014 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003015 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003016
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003017 current_y = current->lineno - edittop->lineno;
3018 if (current_y < editwinrows) {
3019 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003020 wmove(edit, current_y, x - get_page_start(x));
3021 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003022}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003023
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003024/* edit_add() takes care of the job of actually painting a line into the
3025 * edit window. fileptr is the line to be painted, at row yval of the
3026 * window. converted is the actual string to be written to the window,
3027 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003028 * characters. start is the column number of the first character of
3029 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003030 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003031void edit_add(const filestruct *fileptr, const char *converted, int
3032 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003033{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003034#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003035 size_t startpos = actual_x(fileptr->data, start);
3036 /* The position in fileptr->data of the leftmost character
3037 * that displays at least partially on the window. */
3038 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3039 /* The position in fileptr->data of the first character that is
3040 * completely off the window to the right.
3041 *
3042 * Note that endpos might be beyond the null terminator of the
3043 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003044#endif
3045
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003046 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003047 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003048
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003049 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003050 * just the text that needs it). */
3051 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003052
Chris Allegretta7dd77682001-12-08 19:52:28 +00003053#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00003054 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003055 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003056
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003057 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3058 int x_start;
3059 /* Starting column for mvwaddnstr. Zero-based. */
3060 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003061 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003062 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003063 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003064 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003065 regmatch_t startmatch; /* match position for start_regexp */
3066 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003067
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003068 if (tmpcolor->bright)
3069 wattron(edit, A_BOLD);
3070 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003071 /* Two notes about regexec(). Return value 0 means there is
3072 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003073 * after the match. */
3074
3075 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003076 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003077 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003078
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003079 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003080 * last match. Even though two matches may overlap, we
3081 * want to ignore them, so that we can highlight
3082 * C-strings correctly. */
3083 while (k < endpos) {
3084 /* Note the fifth parameter to regexec(). It says
3085 * not to match the beginning-of-line character
3086 * unless k is 0. If regexec() returns REG_NOMATCH,
3087 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003088 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003089 &startmatch, k == 0 ? 0 :
3090 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003091 break;
3092 /* Translate the match to the beginning of the line. */
3093 startmatch.rm_so += k;
3094 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003095 if (startmatch.rm_so == startmatch.rm_eo) {
3096 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00003097 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003098 } else if (startmatch.rm_so < endpos &&
3099 startmatch.rm_eo > startpos) {
3100 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003101 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003102 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003103 x_start = strnlenpt(fileptr->data,
3104 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003105
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003106 index = actual_x(converted, x_start);
3107
3108 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003109 strnlenpt(fileptr->data,
3110 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003111
3112 assert(0 <= x_start && 0 <= paintlen);
3113
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003114 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003115 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003116 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003117 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003118 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003119 } else {
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003120 /* This is a multi-line regexp. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003121 * First, we have to see if the beginning of the line is
3122 * colored by a start on an earlier line, and an end on
3123 * this line or later.
3124 *
3125 * We find the first line before fileptr matching the
3126 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003127 * end, then go to step two. Otherwise, find the next
3128 * line after start_line matching the end. If that line
3129 * is not before fileptr, then paint the beginning of
3130 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003131 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003132 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003133 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003134 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003135 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003136
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003137 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003138 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003139 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003140 /* If there is an end on this line, there is no need
3141 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003142 if (regexec(tmpcolor->end, start_line->data, 0,
3143 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003144 goto step_two;
3145 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003146 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003147 /* No start found, so skip to the next step. */
3148 if (start_line == NULL)
3149 goto step_two;
3150 /* Now start_line is the first line before fileptr
3151 * containing a start match. Is there a start on this
3152 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003153 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003154 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003155 start_col += startmatch.rm_so;
3156 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003157 if (regexec(tmpcolor->end, start_line->data +
3158 start_col + startmatch.rm_eo, 0, NULL,
3159 start_col + startmatch.rm_eo == 0 ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003160 REG_NOTBOL) == REG_NOMATCH)
3161 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003162 break;
3163 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003164 if (regexec(&tmpcolor->start, start_line->data +
3165 start_col, 1, &startmatch,
3166 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003167 /* No later start on this line. */
3168 goto step_two;
3169 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003170 /* Indeed, there is a start not followed on this line by
3171 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003172
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003173 /* We have already checked that there is no end before
3174 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003175 * the start at all? We don't paint unterminated
3176 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003177 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003178 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003179 regexec(tmpcolor->end, end_line->data, 1,
3180 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003181 end_line = end_line->next;
3182
3183 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003184 if (end_line == NULL || (end_line == fileptr &&
3185 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003186 goto step_two;
3187
3188 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003189 if (end_line != fileptr)
3190 /* If the start of fileptr is on a different line
3191 * from the end, paintlen is -1, meaning that
3192 * everything on the line gets painted. */
3193 paintlen = -1;
3194 else
3195 /* Otherwise, paintlen is the expanded location of
3196 * the end of the match minus the expanded location
3197 * of the beginning of the page. */
3198 paintlen = actual_x(converted,
3199 strnlenpt(fileptr->data, endmatch.rm_eo) -
3200 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003201
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003202 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003203
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003204 step_two:
3205 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003206 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003207
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003208 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003209 if (regexec(&tmpcolor->start,
3210 fileptr->data + start_col, 1, &startmatch,
3211 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
3212 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003213 /* No more starts on this line. */
3214 break;
3215 /* Translate the match to be relative to the
3216 * beginning of the line. */
3217 startmatch.rm_so += start_col;
3218 startmatch.rm_eo += start_col;
3219
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003220 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003221 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003222 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003223 x_start = strnlenpt(fileptr->data,
3224 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003225
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003226 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003227
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003228 if (regexec(tmpcolor->end,
3229 fileptr->data + startmatch.rm_eo, 1, &endmatch,
3230 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003231 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003232 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003233 endmatch.rm_so += startmatch.rm_eo;
3234 endmatch.rm_eo += startmatch.rm_eo;
3235 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003236 * appear on this page, and is the match more
3237 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003238 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003239 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003240 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003241 strnlenpt(fileptr->data,
3242 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003243
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003244 assert(0 <= x_start && x_start < COLS);
3245
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003246 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003247 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003248 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003249 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003250 /* There is no end on this line. But we haven't
3251 * yet looked for one on later lines. */
3252 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003253
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003254 while (end_line != NULL &&
3255 regexec(tmpcolor->end, end_line->data,
3256 0, NULL, 0) == REG_NOMATCH)
3257 end_line = end_line->next;
3258
3259 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003260 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003261
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003262 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003263 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003264 /* We painted to the end of the line, so
3265 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003266 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003267 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003268 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003269 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003270 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003271 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003272
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003273 wattroff(edit, A_BOLD);
3274 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
3275 } /* for tmpcolor in colorstrings */
3276 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003277#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003278
Chris Allegretta7dd77682001-12-08 19:52:28 +00003279#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003280 if (ISSET(MARK_ISSET)
3281 && (fileptr->lineno <= mark_beginbuf->lineno
3282 || fileptr->lineno <= current->lineno)
3283 && (fileptr->lineno >= mark_beginbuf->lineno
3284 || fileptr->lineno >= current->lineno)) {
3285 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003286
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003287 const filestruct *top;
3288 /* Either current or mark_beginbuf, whichever is first. */
3289 size_t top_x;
3290 /* current_x or mark_beginx, corresponding to top. */
3291 const filestruct *bot;
3292 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003293 int x_start;
3294 /* Starting column for mvwaddnstr. Zero-based. */
3295 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003296 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003297 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003298 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003299 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003300
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003301 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003302
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003303 if (top->lineno < fileptr->lineno || top_x < startpos)
3304 top_x = startpos;
3305 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3306 bot_x = endpos;
3307
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003308 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003309 if (top_x < endpos && bot_x > startpos) {
3310 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003311
3312 /* x_start is the expanded location of the beginning of the
3313 * mark minus the beginning of the page. */
3314 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003315
3316 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003317 /* If the end of the mark is off the page, paintlen is
3318 * -1, meaning that everything on the line gets
3319 * painted. */
3320 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003321 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003322 /* Otherwise, paintlen is the expanded location of the
3323 * end of the mark minus the expanded location of the
3324 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003325 paintlen = strnlenpt(fileptr->data, bot_x) -
3326 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003327
3328 /* If x_start is before the beginning of the page, shift
3329 * paintlen x_start characters to compensate, and put
3330 * x_start at the beginning of the page. */
3331 if (x_start < 0) {
3332 paintlen += x_start;
3333 x_start = 0;
3334 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003335
3336 assert(x_start >= 0 && x_start <= strlen(converted));
3337
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003338 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003339
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003340 if (paintlen > 0)
3341 paintlen = actual_x(converted + index, paintlen);
3342
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003343 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003344 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003345 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003346 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003347 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003348 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003349#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003350}
3351
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003352/* Just update one line in the edit buffer. This is basically a wrapper
3353 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003354 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003355 * If fileptr != current, then index is considered 0. The line will be
3356 * displayed starting with fileptr->data[index]. Likely args are
3357 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003358void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003359{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003360 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003361 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003362 char *converted;
3363 /* fileptr->data converted to have tabs and control characters
3364 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003365 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003366
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003367 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003368
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003369 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003370
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003371 /* We assume the line numbers are valid. Is that really true? */
3372 assert(line < 0 || line == check_linenumbers(fileptr));
3373
3374 if (line < 0 || line >= editwinrows)
3375 return;
3376
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003377 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003378 mvwaddstr(edit, line, 0, hblank);
3379
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003380 /* Next, convert variables that index the line to their equivalent
3381 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003382 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003383 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003384
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003385 /* Expand the line, replacing tabs with spaces, and control
3386 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003387 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003388
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003389 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003390 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003391 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003392
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003393 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003394 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003395 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003396 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003397}
3398
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003399/* Return a nonzero value if we need an update after moving
3400 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003401 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003402int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003403{
3404 return
3405#ifndef NANO_SMALL
3406 ISSET(MARK_ISSET) ||
3407#endif
3408 get_page_start(old_pww) != get_page_start(placewewant);
3409}
3410
3411/* Return a nonzero value if we need an update after moving vertically.
3412 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003413 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003414int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003415{
3416 return
3417#ifndef NANO_SMALL
3418 ISSET(MARK_ISSET) ||
3419#endif
3420 get_page_start(old_pww) != get_page_start(placewewant);
3421}
3422
3423/* Scroll the edit window in the given direction and the given number
3424 * of lines, and draw new lines on the blank lines left after the
3425 * scrolling. direction is the direction to scroll, either UP or DOWN,
3426 * and nlines is the number of lines to scroll. Don't redraw the old
3427 * topmost or bottommost line (where we assume current is) before
3428 * scrolling or draw the new topmost or bottommost line after scrolling
3429 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003430 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003431void edit_scroll(updown direction, int nlines)
3432{
3433 filestruct *foo;
3434 int i, scroll_rows = 0;
3435
3436 /* Scrolling less than one line or more than editwinrows lines is
3437 * redundant, so don't allow it. */
3438 if (nlines < 1 || nlines > editwinrows)
3439 return;
3440
3441 /* Move the top line of the edit window up or down (depending on the
3442 * value of direction) nlines lines. If there are fewer lines of
3443 * text than that left, move it to the top or bottom line of the
3444 * file (depending on the value of direction). Keep track of
3445 * how many lines we moved in scroll_rows. */
3446 for (i = nlines; i > 0; i--) {
3447 if (direction == UP) {
3448 if (edittop->prev == NULL)
3449 break;
3450 edittop = edittop->prev;
3451 scroll_rows--;
3452 } else {
3453 if (edittop->next == NULL)
3454 break;
3455 edittop = edittop->next;
3456 scroll_rows++;
3457 }
3458 }
3459
3460 /* Scroll the text on the screen up or down scroll_rows lines,
3461 * depending on the value of direction. */
3462 scrollok(edit, TRUE);
3463 wscrl(edit, scroll_rows);
3464 scrollok(edit, FALSE);
3465
3466 foo = edittop;
3467 if (direction != UP) {
3468 int slines = editwinrows - nlines;
3469 for (; slines > 0 && foo != NULL; slines--)
3470 foo = foo->next;
3471 }
3472
3473 /* And draw new lines on the blank top or bottom lines of the edit
3474 * window, depending on the value of direction. Don't draw the new
3475 * topmost or new bottommost line. */
3476 while (scroll_rows != 0 && foo != NULL) {
3477 if (foo->next != NULL)
3478 update_line(foo, 0);
3479 if (direction == UP)
3480 scroll_rows++;
3481 else
3482 scroll_rows--;
3483 foo = foo->next;
3484 }
3485}
3486
3487/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003488 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003489void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003490{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003491 int do_refresh = need_vertical_update(0) ||
3492 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003493 const filestruct *foo;
3494
3495 /* If either old_current or current is offscreen, refresh the screen
3496 * and get out. */
3497 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3498 edittop->lineno + editwinrows || current->lineno <
3499 edittop->lineno || current->lineno >= edittop->lineno +
3500 editwinrows) {
3501 edit_refresh();
3502 return;
3503 }
3504
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003505 /* Update old_current and current if we're not on the first page
3506 * and/or we're not on the same page as before. If the mark is on,
3507 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003508 foo = old_current;
3509 while (foo != current) {
3510 if (do_refresh)
3511 update_line(foo, 0);
3512#ifndef NANO_SMALL
3513 if (!ISSET(MARK_ISSET))
3514#endif
3515 break;
3516 if (foo->lineno > current->lineno)
3517 foo = foo->prev;
3518 else
3519 foo = foo->next;
3520 }
3521 if (do_refresh)
3522 update_line(current, current_x);
3523}
3524
Chris Allegretta6df90f52002-07-19 01:08:59 +00003525/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003526void edit_refresh(void)
3527{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003528 if (current->lineno < edittop->lineno ||
3529 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003530 /* Note that edit_update() changes edittop so that it's in range
3531 * of current. Thus, when it then calls edit_refresh(), there
3532 * is no danger of getting an infinite loop. */
3533 edit_update(
3534#ifndef NANO_SMALL
3535 ISSET(SMOOTHSCROLL) ? NONE :
3536#endif
3537 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003538 else {
3539 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003540 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003541
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003542#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003543 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003544#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003545
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003546 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003547 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003548 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003549 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003550 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003551 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003552 }
3553 while (nlines < editwinrows) {
3554 mvwaddstr(edit, nlines, 0, hblank);
3555 nlines++;
3556 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003557 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003558 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003559 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003560}
3561
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003562/* A nice generic routine to update the edit buffer. We keep current in
3563 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003564void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003565{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003566 filestruct *foo = current;
3567
Chris Allegretta6df90f52002-07-19 01:08:59 +00003568 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003569 /* If location is CENTER, we move edittop up (editwinrows / 2)
3570 * lines. This puts current at the center of the screen. If
3571 * location is NONE, we move edittop up current_y lines if
3572 * current_y is in range of the screen, 0 lines if current_y is
3573 * less than 0, or (editwinrows - 1) lines if current_y is
3574 * greater than (editwinrows - 1). This puts current at the
3575 * same place on the screen as before, or at the top or bottom
3576 * of the screen if edittop is beyond either. */
3577 int goal;
3578
3579 if (location == CENTER)
3580 goal = editwinrows / 2;
3581 else {
3582 goal = current_y;
3583
3584 /* Limit goal to (editwinrows - 1) lines maximum. */
3585 if (goal > editwinrows - 1)
3586 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003587 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003588
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003589 for (; goal > 0 && foo->prev != NULL; goal--)
3590 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003591 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003592
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003593 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003594 edit_refresh();
3595}
3596
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003597/* Ask a simple yes/no question, specified in msg, on the statusbar.
3598 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3599 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003600int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003601{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003602 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003603 const char *yesstr; /* String of yes characters accepted. */
3604 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003605 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003606
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003607 /* yesstr, nostr, and allstr are strings of any length. Each string
3608 * consists of all characters accepted as a valid character for that
3609 * value. The first value will be the one displayed in the
3610 * shortcuts. Translators: if possible, specify both the shortcuts
3611 * for your language and English. For example, in French: "OoYy"
3612 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003613 yesstr = _("Yy");
3614 nostr = _("Nn");
3615 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003616
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003617 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003618 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003619
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003620 if (COLS < 32)
3621 width = COLS / 2;
3622
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003623 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003624 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003625
Chris Allegretta6232d662002-05-12 19:52:15 +00003626 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003627 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003628 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003629
3630 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003631 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003632 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003633 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003634 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003635
Chris Allegrettadb28e962003-01-28 01:23:40 +00003636 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003637 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003638 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003639
Chris Allegrettadb28e962003-01-28 01:23:40 +00003640 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003641 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003642 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003643
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003644 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003645
3646 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003647 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003648
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003649 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003650
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003651 wrefresh(bottomwin);
3652
Chris Allegrettadb28e962003-01-28 01:23:40 +00003653 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003654 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003655 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003656#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003657 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003658#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003659
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003660 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003661
3662 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003663 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003664#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003665 /* Look, ma! We get to duplicate lots of code from
3666 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003667 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003668 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003669
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003670 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003671 wenclose(bottomwin, mouse_y, mouse_x) &&
3672 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003673 int x = mouse_x / width;
3674 /* Did we click in the first column of shortcuts, or
3675 * the second? */
3676 int y = mouse_y - editwinrows - 3;
3677 /* Did we click in the first row of shortcuts? */
3678
3679 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3680
3681 /* x = 0 means they clicked Yes or No.
3682 * y = 0 means Yes or All. */
3683 ok = -2 * x * y + x - y + 1;
3684
3685 if (ok == 2 && !all)
3686 ok = -2;
3687 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003688 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003689#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003690 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003691 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003692 else if (strchr(yesstr, kbinput) != NULL)
3693 ok = 1;
3694 else if (strchr(nostr, kbinput) != NULL)
3695 ok = 0;
3696 else if (all && strchr(allstr, kbinput) != NULL)
3697 ok = 2;
3698 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003699
Chris Allegrettadb28e962003-01-28 01:23:40 +00003700 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003701}
3702
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003703void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003704{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003705 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003706 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003707 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003708 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003709 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003710 wnoutrefresh(bottomwin);
3711 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003712 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003713 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003714 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003715 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003716 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003717 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003718}
3719
3720void display_main_list(void)
3721{
3722 bottombars(main_list);
3723}
3724
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003725/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3726 * display the cursor position. Otherwise, we display it only if the
3727 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003728 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003729 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3730 * old_i and old_totsize. That way, we leave the current statusbar
3731 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003732void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003733{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003734 char c;
3735 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003736 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003737 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003738
Chris Allegrettad26ab912003-01-28 01:16:47 +00003739 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003740
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003741 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003742 old_totsize = totsize;
3743
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003744 c = current->data[current_x];
3745 f = current->next;
3746 current->data[current_x] = '\0';
3747 current->next = NULL;
3748 get_totals(fileage, current, NULL, &i);
3749 current->data[current_x] = c;
3750 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003751
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003752 /* Check whether totsize is correct. Else there is a bug
3753 * somewhere. */
3754 assert(current != filebot || i == totsize);
3755
Chris Allegrettad26ab912003-01-28 01:16:47 +00003756 if (constant && ISSET(DISABLE_CURPOS)) {
3757 UNSET(DISABLE_CURPOS);
3758 old_i = i;
3759 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003760 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003761 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003762
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003763 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003764 * unconditionally; otherwise, only display the position when the
3765 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003766 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003767 size_t xpt = xplustabs() + 1;
3768 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003769 int linepct = 100 * current->lineno / totlines;
3770 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003771 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003772
3773 statusbar(
3774 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3775 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003776 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003777 (unsigned long)i, (unsigned long)totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003778 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003779 }
3780
3781 old_i = i;
3782 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003783}
3784
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003785void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003786{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003787 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003788}
3789
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003790#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003791/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003792int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003793{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003794 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003795
3796 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3797 ptr++;
3798 j++;
3799 }
3800 if (j == COLS - 5) {
3801 /* Don't wrap at the first of two spaces following a period. */
3802 if (*ptr == ' ' && *(ptr + 1) == ' ')
3803 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003804 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003805 while (*ptr != ' ' && j > 0) {
3806 ptr--;
3807 j--;
3808 }
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003809 /* A word longer than (COLS - 5) chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003810 if (j == 0)
3811 j = COLS - 5;
3812 }
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003813
Chris Allegretta4640fe32003-02-10 03:10:03 +00003814 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003815
Chris Allegretta4640fe32003-02-10 03:10:03 +00003816 return j;
3817}
3818
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003819/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003820void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003821{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003822 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003823 /* The line number in help_text of the first displayed help
3824 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003825 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003826 /* no_more means the end of the help text is shown, so don't go
3827 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003828 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003829 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003830
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003831 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003832#ifndef DISABLE_MOUSE
3833 const shortcut *oldshortcut = currshortcut;
3834 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003835 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003836#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003837
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003838 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003839 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003840 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003841 blank_statusbar();
3842
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003843 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003844 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003845 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003846
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003847#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003848 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003849 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003850 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003851#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003852
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003853 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003854 /* Make sure that the help screen's shortcut list will actually
3855 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003856 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003857 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003858 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003859
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003860 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003861
3862 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003863 int i;
3864 int old_line = line;
3865 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003866 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003867
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003868 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003869#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003870 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003871 {
3872 int mouse_x, mouse_y;
3873 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3874 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003875 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003876#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003877 case NANO_NEXTPAGE_KEY:
3878 case NANO_NEXTPAGE_FKEY:
3879 if (!no_more)
3880 line += editwinrows - 2;
3881 break;
3882 case NANO_PREVPAGE_KEY:
3883 case NANO_PREVPAGE_FKEY:
3884 if (line > 0) {
3885 line -= editwinrows - 2;
3886 if (line < 0)
3887 line = 0;
3888 }
3889 break;
3890 case NANO_PREVLINE_KEY:
3891 if (line > 0)
3892 line--;
3893 break;
3894 case NANO_NEXTLINE_KEY:
3895 if (!no_more)
3896 line++;
3897 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003898 }
3899
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003900 if (line == old_line && kbinput != ERR)
3901 goto skip_redisplay;
3902
3903 blank_edit();
3904
3905 assert(COLS > 5);
3906
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003907 /* Calculate where in the text we should be, based on the
3908 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003909 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003910 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003911 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003912 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003913 }
3914
Chris Allegretta4640fe32003-02-10 03:10:03 +00003915 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003916 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003917
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003918 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003919 ptr += j;
3920 if (*ptr == '\n')
3921 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003922 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003923 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003924
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003925 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003926 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003927 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3928 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003929
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003930#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003931 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003932#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003933
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003934 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003935 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003936 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003937 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003938 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003939 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003940 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003941
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003942 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003943 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003944
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003945 /* The help_init() at the beginning allocated help_text. Since
3946 * help_text has now been written to the screen, we don't need it
3947 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003948 free(help_text);
3949 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003950}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003951#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003952
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003953/* Highlight the current word being replaced or spell checked. We
3954 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003955void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003956{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003957 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003958 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003959
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003960 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003961 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003962 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003963
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003964 assert(y > 0);
3965
3966 if (word_len > y)
3967 y--;
3968
Chris Allegrettafb62f732000-12-05 11:36:41 +00003969 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003970
Chris Allegrettafb62f732000-12-05 11:36:41 +00003971 if (highlight_flag)
3972 wattron(edit, A_REVERSE);
3973
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003974#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003975 /* This is so we can show zero-length regexes. */
3976 if (word_len == 0)
3977 waddstr(edit, " ");
3978 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003979#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003980 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003981
3982 if (word_len > y)
3983 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003984
3985 if (highlight_flag)
3986 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003987}
3988
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003989#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003990/* Dump the passed-in file structure to stderr. */
3991void dump_buffer(const filestruct *inptr)
3992{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003993 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003994 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003995 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003996 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003997 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003998 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003999
4000 while (inptr != NULL) {
4001 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4002 inptr = inptr->next;
4003 }
4004}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004005
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004006/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004007void dump_buffer_reverse(void)
4008{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004009 const filestruct *fileptr = filebot;
4010
4011 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004012 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004013 fileptr = fileptr->prev;
4014 }
4015}
4016#endif /* DEBUG */
4017
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004018#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004019#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004020#define XLCREDIT_LEN 8
4021
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004022/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004023void do_credits(void)
4024{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004025 int crpos = 0, xlpos = 0;
4026 const char *credits[CREDIT_LEN] = {
4027 NULL, /* "The nano text editor" */
4028 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004029 VERSION,
4030 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004031 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004032 "Chris Allegretta",
4033 "Jordi Mallach",
4034 "Adam Rogoyski",
4035 "Rob Siemborski",
4036 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004037 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004038 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004039 "Ken Tyler",
4040 "Sven Guckes",
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004041#ifdef NANO_WIDE
David Lawrence Ramsey487d08c2005-01-12 18:16:17 +00004042 !ISSET(NO_UTF8) ? "Florian König" :
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004043#endif
4044 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00004045 "Pauli Virtanen",
4046 "Daniele Medri",
4047 "Clement Laforet",
4048 "Tedi Heriyanto",
4049 "Bill Soudan",
4050 "Christian Weisgerber",
4051 "Erik Andersen",
4052 "Big Gaute",
4053 "Joshua Jensen",
4054 "Ryan Krebs",
4055 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004056 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004057 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004058 "Plattsburgh State University",
4059 "Benet Laboratories",
4060 "Amy Allegretta",
4061 "Linda Young",
4062 "Jeremy Robichaud",
4063 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004064 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004065 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004066 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004067 "Thomas Dickey",
4068 "Pavel Curtis",
4069 "Zeyd Ben-Halim",
4070 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004071 NULL, /* "and anyone else we forgot..." */
4072 NULL, /* "Thank you for using nano!" */
4073 "",
4074 "",
4075 "",
4076 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004077 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004078 "",
4079 "",
4080 "",
4081 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004082 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004083 };
4084
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004085 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004086 N_("The nano text editor"),
4087 N_("version"),
4088 N_("Brought to you by:"),
4089 N_("Special thanks to:"),
4090 N_("The Free Software Foundation"),
4091 N_("For ncurses:"),
4092 N_("and anyone else we forgot..."),
4093 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004094 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004095
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004096 curs_set(0);
4097 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004098 scrollok(edit, TRUE);
4099 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004100 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004101 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004102 blank_statusbar();
4103 blank_bottombars();
4104 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004105 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004106 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004107
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004108 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
4109 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004110 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004111 if (crpos < CREDIT_LEN) {
4112 const char *what = credits[crpos];
4113 size_t start_x;
4114
4115 if (what == NULL) {
4116 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00004117 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004118 xlpos++;
4119 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004120 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramseyeb711b02004-12-05 22:24:39 +00004121 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x,
4122 what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004123 }
4124 napms(700);
4125 scroll(edit);
4126 wrefresh(edit);
4127 if (wgetch(edit) != ERR)
4128 break;
4129 napms(700);
4130 scroll(edit);
4131 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004132 }
4133
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004134 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004135 nodelay(edit, FALSE);
4136 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004137 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004138}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004139#endif