blob: f5db448467f515de40a85d8ae2713f864c04dd3f [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * winio.c *
4 * *
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00005 * Copyright (C) 1999-2005 Chris Allegretta *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00006 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
Jordi Mallach55381aa2004-11-17 23:17:05 +000022#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000025
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000026#include <stdarg.h>
27#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000028#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000029#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000030#include <ctype.h>
Chris Allegretta6232d662002-05-12 19:52:15 +000031#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000032#include "proto.h"
33#include "nano.h"
34
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +000035static int *key_buffer = NULL;
David Lawrence Ramsey74835712004-12-04 17:41:52 +000036 /* The default keystroke buffer,
37 * containing all the keystrokes we have
38 * at a given point. */
39static size_t key_buffer_len = 0;
40 /* The length of the default keystroke
41 * buffer. */
42static int statusblank = 0; /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000043 * we call statusbar(), before we
44 * actually blank the statusbar. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +000045static size_t statusbar_x = (size_t)-1;
46 /* The cursor position in answer. */
47static size_t statusbar_xend = 0;
48 /* The length of answer. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000049static bool resetstatuspos = FALSE;
50 /* Should we reset the cursor position
51 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000052
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000053/* Control character compatibility:
54 *
55 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
56 * VT100, and VT220.
57 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
58 * VT220, and VT320.
59 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
60 * VT220, and VT320.
61 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
62 * VT220, and VT320.
63 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
64 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000065 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000066 * ANSI, VT100, and VT220, and which is Backspace under VT320.
67 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000068 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000069 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
70 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000071 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000072 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000073 * on which the VT320 sequences are translated by the keypad to KEY_DC
74 * and [nothing]. We work around this conflict via the REBIND_DELETE
75 * flag: if it's not set, we assume VT320 compatibility, and if it is,
76 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
77 * Hemel for helping work this conflict out.
78 *
79 * Escape sequence compatibility:
80 *
81 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000082 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000083 * console), xterm, rxvt, and Eterm. Among these, there are several
84 * conflicts and omissions, outlined as follows:
85 *
86 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
87 * (Ctrl-I is also Tab on ANSI, which we already support.)
88 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
89 * NumLock off on Linux console; the latter is omitted. (The editing
90 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000091 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000092 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
93 * latter is omitted. (Mouse input will only work properly if the
94 * extended keypad value KEY_MOUSE is generated on mouse events
95 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000096 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000097 * omitted. (The editing keypad is more important to have working
98 * than the function keys, because the functions of the former are not
99 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000100 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000101 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000102 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000103 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000104 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
105 * omitted. (The arrow keys, with or without modifiers, are more
106 * important to have working than the function keys, because the
107 * functions of the former are not arbitrary and the functions of the
108 * latter are.)
109 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
110 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000111 *
112 * Note that Center (5) on the numeric keypad with NumLock off can also
113 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000114
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000115#ifndef NANO_SMALL
116/* Reset all the input routines that rely on character sequences. */
117void reset_kbinput(void)
118{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000119 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000120 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000121 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000122}
123#endif
124
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000125/* Read in a sequence of keystrokes from win and save them in the
126 * default keystroke buffer. This should only be called when the
127 * default keystroke buffer is empty. */
128void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000129{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000130 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000131
132 /* If the keystroke buffer isn't empty, get out. */
133 if (key_buffer != NULL)
134 return;
135
136 /* Read in the first character using blocking input. */
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000137#ifndef NANO_SMALL
138 allow_pending_sigwinch(TRUE);
139#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000140
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000141 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000142
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000143#ifndef NANO_SMALL
144 allow_pending_sigwinch(FALSE);
145#endif
146
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000147 /* Increment the length of the keystroke buffer, save the value of
148 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000149 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000150 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000151 key_buffer = (int *)nmalloc(sizeof(int));
152 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000153
154 /* Read in the remaining characters using non-blocking input. */
155 nodelay(win, TRUE);
156
157 while (TRUE) {
158#ifndef NANO_SMALL
159 allow_pending_sigwinch(TRUE);
160#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000161
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000162 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000163
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000164 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000165 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000166 break;
167
168 /* Otherwise, increment the length of the keystroke buffer, save
169 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000170 * if the keystroke is an extended keypad value or FALSE if it
171 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000172 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000173 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
174 sizeof(int));
175 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000176
177#ifndef NANO_SMALL
178 allow_pending_sigwinch(FALSE);
179#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000180 }
181
182 /* Switch back to non-blocking input. */
183 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000184}
185
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000186/* Return the length of the default keystroke buffer. */
187size_t get_buffer_len(void)
188{
189 return key_buffer_len;
190}
191
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000192/* Add the contents of the keystroke buffer input to the default
193 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000194void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000195{
196#ifndef NANO_SMALL
197 allow_pending_sigwinch(TRUE);
198 allow_pending_sigwinch(FALSE);
199#endif
200
201 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000202 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000203 return;
204
205 /* If adding input would put the default keystroke buffer beyond
206 * maximum capacity, only add enough of input to put it at maximum
207 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000208 if (key_buffer_len + input_len < key_buffer_len)
209 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000210
211 /* Add the length of input to the length of the default keystroke
212 * buffer, and reallocate the default keystroke buffer so that it
213 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000214 key_buffer_len += input_len;
215 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
216 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000217
218 /* If the default keystroke buffer wasn't empty before, move its
219 * beginning forward far enough so that we can add input to its
220 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000221 if (key_buffer_len > input_len)
222 memmove(key_buffer + input_len, key_buffer,
223 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000224
225 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000226 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000227}
228
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000229/* Put back the character stored in kbinput, putting it in byte range
230 * beforehand. If meta_key is TRUE, put back the Escape character after
231 * putting back kbinput. If func_key is TRUE, put back the function key
232 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000233void unget_kbinput(int kbinput, bool meta_key, bool func_key)
234{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000235 if (!func_key)
236 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000237
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000238 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000239
240 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000241 kbinput = NANO_CONTROL_3;
242 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000243 }
244}
245
246/* Try to read input_len characters from the default keystroke buffer.
247 * If the default keystroke buffer is empty and win isn't NULL, try to
248 * read in more characters from win and add them to the default
249 * keystroke buffer before doing anything else. If the default
250 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000251int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000252{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000253 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000254
255#ifndef NANO_SMALL
256 allow_pending_sigwinch(TRUE);
257 allow_pending_sigwinch(FALSE);
258#endif
259
260 if (key_buffer_len == 0) {
261 if (win != NULL)
262 get_buffer(win);
263
264 if (key_buffer_len == 0)
265 return NULL;
266 }
267
268 /* If input_len is greater than the length of the default keystroke
269 * buffer, only read the number of characters in the default
270 * keystroke buffer. */
271 if (input_len > key_buffer_len)
272 input_len = key_buffer_len;
273
274 /* Subtract input_len from the length of the default keystroke
275 * buffer, and allocate the keystroke buffer input so that it
276 * has enough room for input_len keystrokes. */
277 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000278 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000279
280 /* Copy input_len characters from the beginning of the default
281 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000282 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000283
284 /* If the default keystroke buffer is empty, mark it as such. */
285 if (key_buffer_len == 0) {
286 free(key_buffer);
287 key_buffer = NULL;
288 /* If the default keystroke buffer isn't empty, move its
289 * beginning forward far enough back so that the keystrokes in input
290 * are no longer at its beginning. */
291 } else {
292 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000293 sizeof(int));
294 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
295 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000296 }
297
298 return input;
299}
300
301/* Read in a single character. If it's ignored, swallow it and go on.
302 * Otherwise, try to translate it from ASCII, meta key sequences, escape
303 * sequences, and/or extended keypad values. Set meta_key to TRUE when
304 * we get a meta key sequence, and set func_key to TRUE when we get an
305 * extended keypad value. Supported extended keypad values consist of
306 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
307 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
308 * the function keypad (F1-F16), and the numeric keypad with NumLock
309 * off. Assume nodelay(win) is FALSE. */
310int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
311{
312 int kbinput;
313
314 /* Read in a character and interpret it. Continue doing this until
315 * we get a recognized value or sequence. */
316 while ((kbinput = parse_kbinput(win, meta_key, func_key
317#ifndef NANO_SMALL
318 , FALSE
319#endif
320 )) == ERR);
321
322 return kbinput;
323}
324
325/* Translate ASCII characters, extended keypad values, and escape
326 * sequences into their corresponding key values. Set meta_key to TRUE
327 * when we get a meta key sequence, and set func_key to TRUE when we get
328 * a function key. Assume nodelay(win) is FALSE. */
329int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000330#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000331 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000332#endif
333 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000334
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000335{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000336 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000337 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000338
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000339#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000340 if (reset) {
341 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000342 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000343 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000344 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000345#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000346
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000347 *meta_key = FALSE;
348 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000349
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000350 /* Read in a character. */
351 while ((kbinput = get_input(win, 1)) == NULL);
352
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000353 switch (*kbinput) {
354 case ERR:
355 break;
356 case NANO_CONTROL_3:
357 /* Increment the escape counter. */
358 escapes++;
359 switch (escapes) {
360 case 1:
361 /* One escape: wait for more input. */
362 case 2:
363 /* Two escapes: wait for more input. */
364 break;
365 default:
366 /* More than two escapes: reset the escape counter
367 * and wait for more input. */
368 escapes = 0;
369 }
370 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000371#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000372 /* Since we don't change the default SIGWINCH handler when
373 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
374 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
375 case KEY_RESIZE:
376 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000377#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000378#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000379 case KEY_SHIFT_L:
380 case KEY_SHIFT_R:
381 case KEY_CONTROL_L:
382 case KEY_CONTROL_R:
383 case KEY_ALT_L:
384 case KEY_ALT_R:
385 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000386#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000387 default:
388 switch (escapes) {
389 case 0:
390 switch (*kbinput) {
391 case NANO_CONTROL_8:
392 retval = ISSET(REBIND_DELETE) ?
393 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
394 break;
395 case KEY_DOWN:
396 retval = NANO_NEXTLINE_KEY;
397 break;
398 case KEY_UP:
399 retval = NANO_PREVLINE_KEY;
400 break;
401 case KEY_LEFT:
402 retval = NANO_BACK_KEY;
403 break;
404 case KEY_RIGHT:
405 retval = NANO_FORWARD_KEY;
406 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000407#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000408 /* HP-UX 10 and 11 don't support KEY_HOME. */
409 case KEY_HOME:
410 retval = NANO_HOME_KEY;
411 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000412#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000413 case KEY_BACKSPACE:
414 retval = NANO_BACKSPACE_KEY;
415 break;
416 case KEY_DC:
417 retval = ISSET(REBIND_DELETE) ?
418 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
419 break;
420 case KEY_IC:
421 retval = NANO_INSERTFILE_KEY;
422 break;
423 case KEY_NPAGE:
424 retval = NANO_NEXTPAGE_KEY;
425 break;
426 case KEY_PPAGE:
427 retval = NANO_PREVPAGE_KEY;
428 break;
429 case KEY_ENTER:
430 retval = NANO_ENTER_KEY;
431 break;
432 case KEY_A1: /* Home (7) on numeric keypad
433 * with NumLock off. */
434 retval = NANO_HOME_KEY;
435 break;
436 case KEY_A3: /* PageUp (9) on numeric keypad
437 * with NumLock off. */
438 retval = NANO_PREVPAGE_KEY;
439 break;
440 case KEY_B2: /* Center (5) on numeric keypad
441 * with NumLock off. */
442 break;
443 case KEY_C1: /* End (1) on numeric keypad
444 * with NumLock off. */
445 retval = NANO_END_KEY;
446 break;
447 case KEY_C3: /* PageDown (4) on numeric
448 * keypad with NumLock off. */
449 retval = NANO_NEXTPAGE_KEY;
450 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000451#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000452 /* Slang doesn't support KEY_BEG. */
453 case KEY_BEG: /* Center (5) on numeric keypad
454 * with NumLock off. */
455 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000456#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000457#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000458 /* HP-UX 10 and 11 don't support KEY_END. */
459 case KEY_END:
460 retval = NANO_END_KEY;
461 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000462#endif
463#ifdef KEY_SUSPEND
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000464 /* Slang doesn't support KEY_SUSPEND. */
465 case KEY_SUSPEND:
466 retval = NANO_SUSPEND_KEY;
467 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000468#endif
469#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000470 /* Slang doesn't support KEY_SLEFT. */
471 case KEY_SLEFT:
472 retval = NANO_BACK_KEY;
473 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000474#endif
475#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000476 /* Slang doesn't support KEY_SRIGHT. */
477 case KEY_SRIGHT:
478 retval = NANO_FORWARD_KEY;
479 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000480#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000481 default:
482 retval = *kbinput;
483 break;
484 }
485 break;
486 case 1:
487 /* One escape followed by a non-escape: escape
488 * sequence mode. Reset the escape counter. If
489 * there aren't any other keys waiting, we have a
490 * meta key sequence, so set meta_key to TRUE and
491 * save the lowercase version of the non-escape
492 * character as the result. If there are other keys
493 * waiting, we have a true escape sequence, so
494 * interpret it. */
495 escapes = 0;
496 if (get_buffer_len() == 0) {
497 *meta_key = TRUE;
498 retval = tolower(*kbinput);
499 } else {
500 int *seq;
501 size_t seq_len;
502 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000503
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000504 /* Put back the non-escape character, get the
505 * complete escape sequence, translate the
506 * sequence into its corresponding key value,
507 * and save that as the result. */
508 unget_input(kbinput, 1);
509 seq_len = get_buffer_len();
510 seq = get_input(NULL, seq_len);
511 retval = get_escape_seq_kbinput(seq, seq_len,
512 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000513
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000514 /* If the escape sequence is unrecognized and
515 * not ignored, put back all of its characters
516 * except for the initial escape. */
517 if (retval == ERR && !ignore_seq)
518 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000519
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000520 free(seq);
521 }
522 break;
523 case 2:
524 /* Two escapes followed by one or more decimal
525 * digits: byte sequence mode. If the word
526 * sequence's range is limited to 2XX (the first
527 * digit is in the '0' to '2' range and it's the
528 * first digit, or it's in the '0' to '9' range and
529 * it's not the first digit), increment the byte
530 * sequence counter and interpret the digit. If the
531 * byte sequence's range is not limited to 2XX, fall
532 * through. */
533 if (('0' <= *kbinput && *kbinput <= '6' &&
534 byte_digits == 0) || ('0' <= *kbinput &&
535 *kbinput <= '9' && byte_digits > 0)) {
536 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000537
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000538 byte_digits++;
539 byte = get_byte_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000540#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000541 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000542#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000543 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000544
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000545 if (byte != ERR) {
546 char *byte_mb = charalloc(mb_cur_max());
547 int byte_mb_len, *seq, i;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000548
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000549 /* If we've read in a complete byte
550 * sequence, reset the byte sequence counter
551 * and the escape counter, and put back the
552 * corresponding byte value. */
553 byte_digits = 0;
554 escapes = 0;
555
556 /* Put back the multibyte equivalent of the
557 * byte value. */
558 byte_mb = make_mbchar(byte, byte_mb,
559 &byte_mb_len);
560
561 seq = (int *)nmalloc(byte_mb_len *
562 sizeof(int));
563
564 for (i = 0; i < byte_mb_len; i++)
565 seq[i] = (unsigned char)byte_mb[i];
566
567 unget_input(seq, byte_mb_len);
568
569 free(seq);
570 free(byte_mb);
571 }
572 } else {
573 /* Reset the escape counter. */
574 escapes = 0;
575 if (byte_digits == 0)
576 /* Two escapes followed by a non-decimal
577 * digit or a decimal digit that would
578 * create a byte sequence greater than 2XX,
579 * and we're not in the middle of a byte
580 * sequence: control character sequence
581 * mode. Interpret the control sequence and
582 * save the corresponding control character
583 * as the result. */
584 retval = get_control_kbinput(*kbinput);
585 else {
586 /* If we're in the middle of a byte
587 * sequence, reset the byte sequence counter
588 * and save the character we got as the
589 * result. */
590 byte_digits = 0;
591 retval = *kbinput;
592 }
593 }
594 break;
595 }
596 }
597
598 /* If we have a result and it's an extended keypad value (i.e, a
599 * value outside of byte range), set func_key to TRUE. */
600 if (retval != ERR)
601 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000602
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000603#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000604 fprintf(stderr, "parse_kbinput(): kbinput = %d, meta_key = %d, func_key = %d, escapes = %d, byte_digits = %d, retval = %d\n", *kbinput, (int)*meta_key, (int)*func_key, escapes, byte_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000605#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000606
607 /* Return the result. */
608 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000609}
610
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000611/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000612 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000613 * are generated when the keypad doesn't support the needed keys. If
614 * the escape sequence is recognized but we want to ignore it, return
615 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
616 * set ignore_seq to FALSE. Assume that Escape has already been read
617 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000618int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000619 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000620{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000621 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000622
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000623 *ignore_seq = FALSE;
624
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000625 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000626 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000627 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000628 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000629 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000630 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000631 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000632 case 'P': /* Esc O 2 P == F13 on
633 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000634 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000635 break;
636 case 'Q': /* Esc O 2 Q == F14 on
637 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000638 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000639 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000640 case 'R': /* Esc O 2 R == F15 on
641 * xterm. */
642 retval = KEY_F(15);
643 break;
644 case 'S': /* Esc O 2 S == F16 on
645 * xterm. */
646 retval = KEY_F(16);
647 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000648 }
649 }
650 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000651 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
652 case 'B': /* Esc O B == Down on
653 * VT100/VT320/xterm. */
654 case 'C': /* Esc O C == Right on
655 * VT100/VT320/xterm. */
656 case 'D': /* Esc O D == Left on
657 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000658 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000659 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000660 case 'E': /* Esc O E == Center (5) on numeric keypad
661 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000662 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000663 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000664 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000665 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000666 break;
667 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000668 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000669 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000670 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000671 * NumLock off on VT100/VT220/VT320/xterm/
672 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000673 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000674 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000675 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000676 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000677 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000678 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000679 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000680 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000681 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000682 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000683 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000684 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000685 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000686 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000687 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000688 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000689 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000690 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000691 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000692 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000693 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000694 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000695 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000696 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000697 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000698 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000699 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000700 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000701 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000702 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000703 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000704 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000705 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000706 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000707 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000708 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000709 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000710 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000711 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000712 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000713 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000714 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000715 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000716 * NumLock off on VT100/VT220/VT320/xterm/
717 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000718 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000719 break;
720 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000721 * NumLock off on VT100/VT220/VT320/xterm/
722 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000723 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000724 break;
725 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000726 * NumLock off on VT100/VT220/VT320/xterm/
727 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000728 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000729 break;
730 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000731 * NumLock off on VT100/VT220/VT320/xterm/
732 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000733 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000734 break;
735 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000736 * with NumLock off on VT100/VT220/VT320/
737 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000738 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000739 break;
740 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000741 * NumLock off on VT100/VT220/VT320/xterm/
742 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000743 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000744 break;
745 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000746 * with NumLock off on VT100/VT220/VT320/
747 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000748 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000749 break;
750 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000751 * with NumLock off on VT100/VT220/VT320/
752 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000753 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000754 break;
755 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000756 * with NumLock off on VT100/VT220/VT320/
757 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000758 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000759 break;
760 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000761 * keypad with NumLock off on VT100/VT220/
762 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000763 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000764 break;
765 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000766 * with NumLock off on VT100/VT220/VT320/
767 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000768 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000769 break;
770 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000771 * with NumLock off on VT100/VT220/VT320/
772 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000773 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000774 break;
775 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000776 * with NumLock off on VT100/VT220/VT320/
777 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000778 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000779 break;
780 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000781 * with NumLock off on VT100/VT220/VT320/
782 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000783 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000784 break;
785 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000786 * with NumLock off on VT100/VT220/VT320/
787 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000788 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000789 break;
790 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000791 * with NumLock off on VT100/VT220/VT320/
792 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000793 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000794 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000795 }
796 break;
797 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000798 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000799 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000800 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000801 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000802 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000803 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000804 break;
805 }
806 break;
807 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000808 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000809 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000810 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000811 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000812 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
813 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000814 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000815 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000816 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
817 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000818 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000819 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000820 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
821 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000822 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000823 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000824 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
825 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000826 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000827 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000828 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
829 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000830 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000831 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000832 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000833 * VT220/VT320/Linux console/
834 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000835 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000836 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000837 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000838 * VT220/VT320/Linux console/
839 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000840 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000841 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000842 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000843 * VT220/VT320/Linux console/
844 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000845 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000846 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000847 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000848 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000849 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000850 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000851 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000852 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000853 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
854 * xterm. */
855 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
856 * xterm. */
857 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
858 * xterm. */
859 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
860 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000861 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000862 break;
863 }
864 }
865 break;
866 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000867 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000868 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000869 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
870 * xterm. */
871 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
872 * xterm. */
873 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
874 * xterm. */
875 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
876 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000877 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000878 break;
879 }
880 }
881 break;
882 }
883 }
884 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000885 default: /* Esc [ 1 ~ == Home on
886 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000887 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000888 break;
889 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000890 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000891 break;
892 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000893 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000894 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000895 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000896 * VT220/VT320/Linux console/
897 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000898 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000899 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000900 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000901 * VT220/VT320/Linux console/
902 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000903 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000904 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000905 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000906 * VT220/VT320/Linux console/
907 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000908 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000909 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000910 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000911 * VT220/VT320/Linux console/
912 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000913 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000914 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000915 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000916 * VT220/VT320/Linux console/
917 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000918 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000919 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000920 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000921 * VT220/VT320/Linux console/
922 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000923 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000924 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000925 case '8': /* Esc [ 2 8 ~ == F15 on
926 * VT220/VT320/Linux console/
927 * rxvt/Eterm. */
928 retval = KEY_F(15);
929 break;
930 case '9': /* Esc [ 2 9 ~ == F16 on
931 * VT220/VT320/Linux console/
932 * rxvt/Eterm. */
933 retval = KEY_F(16);
934 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000935 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000936 * VT220/VT320/Linux console/
937 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000938 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000939 break;
940 }
941 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000942 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000943 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
944 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000945 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000946 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000947 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000948 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000949 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000950 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000951 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
952 * Linux console/xterm; Esc [ 5 ^ ==
953 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000954 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000955 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000956 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
957 * Linux console/xterm; Esc [ 6 ^ ==
958 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000959 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000960 break;
961 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000962 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000963 break;
964 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000965 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000966 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000967 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000968 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000969 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000970 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000971 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000972 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000973 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000974 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000975 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000976 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000977 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000978 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000979 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000980 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000981 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000982 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000983 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000984 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000985 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000986 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000987 case 'E': /* Esc [ E == Center (5) on numeric keypad
988 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000989 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000990 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000991 case 'F': /* Esc [ F == End on FreeBSD
992 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000993 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000994 break;
995 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000996 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000997 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000998 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000999 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001000 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001001 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001002 break;
1003 case 'I': /* Esc [ I == PageUp on FreeBSD
1004 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001005 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001006 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001007 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001008 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001009 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001010 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001011 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001012 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001013 break;
1014 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001015 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001016 break;
1017 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001018 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001019 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001020 case 'P': /* Esc [ O P == F1 on
1021 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001022 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001023 break;
1024 case 'Q': /* Esc [ O Q == F2 on
1025 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001026 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001027 break;
1028 case 'R': /* Esc [ O R == F3 on
1029 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001030 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001031 break;
1032 case 'S': /* Esc [ O S == F4 on
1033 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001034 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001035 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001036 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001037 } else {
1038 /* Esc [ O == F3 on FreeBSD console. */
1039 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001040 }
1041 break;
1042 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001043 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001044 break;
1045 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001046 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001047 break;
1048 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001049 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001050 break;
1051 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001052 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001053 break;
1054 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001055 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001056 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001057 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001058 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001059 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001060 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001062 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001063 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001064 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001065 break;
1066 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001067 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001068 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001069 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001070 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001071 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001072 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001073 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001074 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001075 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001076 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001077 case 'c': /* Esc [ c == Shift-Right on rxvt/
1078 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001079 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001080 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001081 break;
1082 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001083 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001084 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001085 case 'A': /* Esc [ [ A == F1 on Linux
1086 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001087 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001088 break;
1089 case 'B': /* Esc [ [ B == F2 on Linux
1090 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001091 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001092 break;
1093 case 'C': /* Esc [ [ C == F3 on Linux
1094 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001095 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001096 break;
1097 case 'D': /* Esc [ [ D == F4 on Linux
1098 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001099 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001100 break;
1101 case 'E': /* Esc [ [ E == F5 on Linux
1102 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001103 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001104 break;
1105 }
1106 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001107 break;
1108 }
1109 break;
1110 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001111 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001112
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001113#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001114 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001115#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001116
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001117 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001118}
1119
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001120/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001121 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001122 * to many escape sequences. */
1123int get_escape_seq_abcd(int kbinput)
1124{
1125 switch (tolower(kbinput)) {
1126 case 'a':
1127 return NANO_PREVLINE_KEY;
1128 case 'b':
1129 return NANO_NEXTLINE_KEY;
1130 case 'c':
1131 return NANO_FORWARD_KEY;
1132 case 'd':
1133 return NANO_BACK_KEY;
1134 default:
1135 return ERR;
1136 }
1137}
1138
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001139/* Translate a byte sequence: turn a three-digit decimal number from
1140 * 000 to 255 into its corresponding byte value. */
1141int get_byte_kbinput(int kbinput
1142#ifndef NANO_SMALL
1143 , bool reset
1144#endif
1145 )
1146{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001147 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001148 int retval = ERR;
1149
1150#ifndef NANO_SMALL
1151 if (reset) {
1152 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001153 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001154 return ERR;
1155 }
1156#endif
1157
1158 /* Increment the byte digit counter. */
1159 byte_digits++;
1160
1161 switch (byte_digits) {
1162 case 1:
1163 /* One digit: reset the byte sequence holder and add the
1164 * digit we got to the 100's position of the byte sequence
1165 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001166 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001167 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001168 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001169 else
1170 /* If the character we got isn't a decimal digit, or if
1171 * it is and it would put the byte sequence out of byte
1172 * range, save it as the result. */
1173 retval = kbinput;
1174 break;
1175 case 2:
1176 /* Two digits: add the digit we got to the 10's position of
1177 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001178 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1179 '6' <= kbinput && kbinput <= '9'))
1180 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001181 else
1182 /* If the character we got isn't a decimal digit, or if
1183 * it is and it would put the byte sequence out of byte
1184 * range, save it as the result. */
1185 retval = kbinput;
1186 break;
1187 case 3:
1188 /* Three digits: add the digit we got to the 1's position of
1189 * the byte sequence holder, and save the corresponding word
1190 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001191 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1192 '6' <= kbinput && kbinput <= '9')) {
1193 byte += (kbinput - '0');
1194 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001195 } else
1196 /* If the character we got isn't a decimal digit, or if
1197 * it is and it would put the word sequence out of word
1198 * range, save it as the result. */
1199 retval = kbinput;
1200 break;
1201 default:
1202 /* More than three digits: save the character we got as the
1203 * result. */
1204 retval = kbinput;
1205 break;
1206 }
1207
1208 /* If we have a result, reset the byte digit counter and the byte
1209 * sequence holder. */
1210 if (retval != ERR) {
1211 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001212 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001213 }
1214
1215#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001216 fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte = %d, retval = %d\n", kbinput, byte_digits, byte, retval);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001217#endif
1218
1219 return retval;
1220}
1221
1222/* Translate a word sequence: turn a four-digit hexadecimal number from
1223 * 0000 to ffff (case-insensitive) into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001224int get_word_kbinput(int kbinput
1225#ifndef NANO_SMALL
1226 , bool reset
1227#endif
1228 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001229{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001230 static int word_digits = 0, word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001231 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001232
1233#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001234 if (reset) {
1235 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001236 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001237 return ERR;
1238 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001239#endif
1240
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001241 /* Increment the word digit counter. */
1242 word_digits++;
1243
1244 switch (word_digits) {
1245 case 1:
1246 /* One digit: reset the word sequence holder and add the
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001247 * digit we got to the 4096's position of the word sequence
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001248 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001249 word = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001250 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001251 word += (kbinput - '0') * 4096;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001252 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001253 word += (tolower(kbinput) + 10 - 'a') * 4096;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001254 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001255 /* If the character we got isn't a hexadecimal digit, or
1256 * if it is and it would put the word sequence out of
1257 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001258 retval = kbinput;
1259 break;
1260 case 2:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001261 /* Two digits: add the digit we got to the 256's position of
1262 * the word sequence holder. */
1263 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001264 word += (kbinput - '0') * 256;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001265 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001266 word += (tolower(kbinput) + 10 - 'a') * 256;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001267 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001268 /* If the character we got isn't a hexadecimal digit, or
1269 * if it is and it would put the word sequence out of
1270 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001271 retval = kbinput;
1272 break;
1273 case 3:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001274 /* Three digits: add the digit we got to the 16's position
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001275 * of the word sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001276 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001277 word += (kbinput - '0') * 16;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001278 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001279 word += (tolower(kbinput) + 10 - 'a') * 16;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001280 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001281 /* If the character we got isn't a hexadecimal digit, or
1282 * if it is and it would put the word sequence out of
1283 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001284 retval = kbinput;
1285 break;
1286 case 4:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001287 /* Four digits: add the digit we got to the 1's position of
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001288 * the word sequence holder, and save the corresponding word
1289 * value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001290 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001291 word += (kbinput - '0');
1292 retval = word;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001293 } else if ('a' <= tolower(kbinput) &&
1294 tolower(kbinput) <= 'f') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001295 word += (tolower(kbinput) + 10 - 'a');
1296 retval = word;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001297 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001298 /* If the character we got isn't a hexadecimal digit, or
1299 * if it is and it would put the word sequence out of
1300 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001301 retval = kbinput;
1302 break;
1303 default:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001304 /* More than four digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001305 * result. */
1306 retval = kbinput;
1307 break;
1308 }
1309
1310 /* If we have a result, reset the word digit counter and the word
1311 * sequence holder. */
1312 if (retval != ERR) {
1313 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001314 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001315 }
1316
1317#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001318 fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word = %d, retval = %d\n", kbinput, word_digits, word, retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001319#endif
1320
1321 return retval;
1322}
1323
1324/* Translate a control character sequence: turn an ASCII non-control
1325 * character into its corresponding control character. */
1326int get_control_kbinput(int kbinput)
1327{
1328 int retval;
1329
1330 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1331 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1332 kbinput == '`')
1333 retval = NANO_CONTROL_SPACE;
1334 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1335 else if ('3' <= kbinput && kbinput <= '7')
1336 retval = kbinput - 24;
1337 /* Ctrl-8 (Ctrl-?) */
1338 else if (kbinput == '8' || kbinput == '?')
1339 retval = NANO_CONTROL_8;
1340 /* Ctrl-A to Ctrl-_ */
1341 else if ('A' <= kbinput && kbinput <= '_')
1342 retval = kbinput - 64;
1343 /* Ctrl-a to Ctrl-~ */
1344 else if ('a' <= kbinput && kbinput <= '~')
1345 retval = kbinput - 96;
1346 else
1347 retval = kbinput;
1348
1349#ifdef DEBUG
1350 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1351#endif
1352
1353 return retval;
1354}
1355
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001356/* Put the output-formatted characters in output back into the default
1357 * keystroke buffer, so that they can be parsed and displayed as output
1358 * again. */
1359void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001360{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001361 int *input;
1362 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001363
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001364 if (output_len == 0)
1365 return;
1366
1367 input = (int *)nmalloc(output_len * sizeof(int));
1368 for (i = 0; i < output_len; i++)
1369 input[i] = (int)output[i];
1370 unget_input(input, output_len);
1371 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001372}
1373
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001374/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001375 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1376int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1377{
1378 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001379
1380 /* Turn off flow control characters if necessary so that we can type
1381 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001382 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001383 if (ISSET(PRESERVE))
1384 disable_flow_control();
1385 keypad(win, FALSE);
1386
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001387 /* Read in a stream of characters and interpret it if possible. */
1388 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001389
1390 /* Turn flow control characters back on if necessary and turn the
1391 * keypad back on now that we're done. */
1392 if (ISSET(PRESERVE))
1393 enable_flow_control();
1394 keypad(win, TRUE);
1395
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001396 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001397}
1398
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001399/* Read in a stream of all available characters, and return the length
1400 * of the string in kbinput_len. Translate the first few characters of
1401 * the input into the corresponding word value if possible. After that,
1402 * leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001403int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001404{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001405 int *kbinput, word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001406
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001407 /* Read in the first keystroke. */
1408 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001409
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001410 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001411 word = get_word_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001412#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001413 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001414#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001415 );
1416
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001417 /* If the first keystroke isn't a hexadecimal digit, put back the
1418 * first keystroke. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001419 if (word != ERR)
1420 unget_input(kbinput, 1);
1421 /* Otherwise, read in keystrokes until we have a complete word
1422 * sequence, and put back the corresponding word value. */
1423 else {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001424 char *word_mb = charalloc(mb_cur_max());
1425 int word_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001426
1427 while (word == ERR) {
1428 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001429
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001430 word = get_word_kbinput(*kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001431#ifndef NANO_SMALL
1432 , FALSE
1433#endif
1434 );
1435 }
1436
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001437 /* Put back the multibyte equivalent of the word value. */
1438 word_mb = make_mbchar(word, word_mb, &word_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001439
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001440 seq = (int *)nmalloc(word_mb_len * sizeof(int));
1441
1442 for (i = 0; i < word_mb_len; i++)
1443 seq[i] = (unsigned char)word_mb[i];
1444
1445 unget_input(seq, word_mb_len);
1446
1447 free(seq);
1448 free(word_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001449 }
1450
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001451 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001452 * result. */
1453 *kbinput_len = get_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001454 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001455
1456 return retval;
1457}
1458
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001459#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001460/* Check for a mouse event, and if one's taken place, save the
1461 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001462 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1463 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001464 * place on it, figure out which shortcut was clicked and put back the
1465 * equivalent keystroke(s). Return FALSE if no keystrokes were
1466 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001467 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001468bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001469{
1470 MEVENT mevent;
1471
1472 *mouse_x = -1;
1473 *mouse_y = -1;
1474
1475 /* First, get the actual mouse event. */
1476 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001477 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001478
1479 /* Save the screen coordinates where the mouse event took place. */
1480 *mouse_x = mevent.x;
1481 *mouse_y = mevent.y;
1482
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001483 /* If we're allowing shortcuts, the current shortcut list is being
1484 * displayed on the last two lines of the screen, and the mouse
1485 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001486 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001487 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1488 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001489 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001490 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001491 /* The number of shortcuts in the current shortcut list. */
1492 const shortcut *s = currshortcut;
1493 /* The actual shortcut we clicked on, starting at the first
1494 * one in the current shortcut list. */
1495
1496 /* Get the shortcut lists' length. */
1497 if (currshortcut == main_list)
1498 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001499 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001500 currslen = length_of_list(currshortcut);
1501
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001502 /* We don't show any more shortcuts than the main list
1503 * does. */
1504 if (currslen > MAIN_VISIBLE)
1505 currslen = MAIN_VISIBLE;
1506 }
1507
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001508 /* Calculate the width of each shortcut in the list (it's the
1509 * same for all of them). */
1510 if (currslen < 2)
1511 i = COLS / 6;
1512 else
1513 i = COLS / ((currslen / 2) + (currslen % 2));
1514
1515 /* Calculate the y-coordinates relative to the beginning of
1516 * bottomwin, i.e, the bottom three lines of the screen. */
1517 j = *mouse_y - (editwinrows + 3);
1518
1519 /* If we're on the statusbar, beyond the end of the shortcut
1520 * list, or beyond the end of a shortcut on the right side of
1521 * the screen, don't do anything. */
1522 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001523 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001524 j = (*mouse_x / i) * 2 + j;
1525 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001526 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001527
1528 /* Go through the shortcut list to determine which shortcut was
1529 * clicked. */
1530 for (; j > 0; j--)
1531 s = s->next;
1532
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001533 /* And put back the equivalent key. Assume that each shortcut
1534 * has, at the very least, an equivalent control key, an
1535 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001536 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001537 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001538 return TRUE;
1539 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001540 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001541 return TRUE;
1542 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001543 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001544 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001545}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001546#endif /* !DISABLE_MOUSE */
1547
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001548const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001549 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001550{
1551 const shortcut *s = s_list;
1552 size_t slen = length_of_list(s_list);
1553
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001554#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001555 fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %d, func_key = %d\n", *kbinput, (int)*meta_key, (int)*func_key);
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001556#endif
1557
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001558 /* Check for shortcuts. */
1559 for (; slen > 0; slen--) {
1560 /* We've found a shortcut if:
1561 *
1562 * 1. The key exists.
1563 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001564 * 3. meta_key is TRUE and the key is the primary or
1565 * miscellaneous meta sequence in the shortcut list.
1566 * 4. func_key is TRUE and the key is a function key in the
1567 * shortcut list. */
1568
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001569 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1570 (*meta_key == TRUE && (*kbinput == s->metaval ||
1571 *kbinput == s->miscval)) || (*func_key == TRUE &&
1572 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001573 break;
1574 }
1575
1576 s = s->next;
1577 }
1578
1579 /* Translate the shortcut to either its control key or its meta key
1580 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001581 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001582 if (slen > 0) {
1583 if (s->ctrlval != NANO_NO_KEY) {
1584 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001585 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001586 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001587 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001588 } else if (s->metaval != NANO_NO_KEY) {
1589 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001590 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001591 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001592 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001593 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001594 }
1595
1596 return NULL;
1597}
1598
1599#ifndef NANO_SMALL
1600const toggle *get_toggle(int kbinput, bool meta_key)
1601{
1602 const toggle *t = toggles;
1603
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001604#ifdef DEBUG
1605 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1606#endif
1607
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001608 /* Check for toggles. */
1609 for (; t != NULL; t = t->next) {
1610 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001611 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001612 if (meta_key && kbinput == t->val)
1613 break;
1614 }
1615
1616 return t;
1617}
1618#endif /* !NANO_SMALL */
1619
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001620int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001621 bool *ran_func, bool *finished, bool allow_funcs)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001622{
1623 int input;
1624 /* The character we read in. */
1625 static int *kbinput = NULL;
1626 /* The input buffer. */
1627 static size_t kbinput_len = 0;
1628 /* The length of the input buffer. */
1629 const shortcut *s;
1630 bool have_shortcut;
1631
1632 *s_or_t = FALSE;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001633 *ran_func = FALSE;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001634 *finished = FALSE;
1635
1636 /* Read in a character. */
1637 input = get_kbinput(bottomwin, meta_key, func_key);
1638
1639#ifndef DISABLE_MOUSE
1640 /* If we got a mouse click and it was on a shortcut, read in the
1641 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001642 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001643 if (do_mouse())
1644 input = get_kbinput(bottomwin, meta_key, func_key);
1645 else
1646 input = ERR;
1647 }
1648#endif
1649
1650 /* Check for a shortcut in the current list. */
1651 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1652
1653 /* If we got a shortcut from the current list, or a "universal"
1654 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1655 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1656 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1657 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1658 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001659 input == NANO_CUT_KEY || (*meta_key == TRUE &&
1660 input == NANO_VERBATIM_KEY));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001661
1662 /* Set s_or_t to TRUE if we got a shortcut. */
1663 *s_or_t = have_shortcut;
1664
1665 if (allow_funcs) {
1666 if (input != ERR && *s_or_t == FALSE && !is_cntrl_char(input)) {
1667 /* If we're using restricted mode, the filename isn't blank,
1668 * and we're at the "Write File" prompt, disable text
1669 * input. */
1670 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1671 currshortcut != writefile_list) {
1672 kbinput_len++;
1673 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1674 sizeof(int));
1675 kbinput[kbinput_len - 1] = input;
1676 }
1677 }
1678
1679 /* If we got a shortcut, or if there aren't any other characters
1680 * waiting after the one we read in, we need to display all the
1681 * characters in the input buffer if it isn't empty. */
1682 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1683 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001684
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001685 /* Display all the characters in the input buffer at
1686 * once. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001687 char *output = charalloc(kbinput_len + 1);
1688 size_t i;
1689 bool got_enter;
1690 /* Whether we got the Enter key. */
1691
1692 for (i = 0; i < kbinput_len; i++)
1693 output[i] = (char)kbinput[i];
1694 output[i] = '\0';
1695
1696 do_statusbar_output(output, kbinput_len, &got_enter);
1697
1698 free(output);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001699
1700 /* Empty the input buffer. */
1701 kbinput_len = 0;
1702 free(kbinput);
1703 kbinput = NULL;
1704 }
1705 }
1706
1707 if (have_shortcut) {
1708 switch (input) {
1709 /* Handle the "universal" statusbar prompt shortcuts. */
1710 case NANO_REFRESH_KEY:
1711 total_refresh();
1712 break;
1713 case NANO_HOME_KEY:
1714 do_statusbar_home();
1715 break;
1716 case NANO_END_KEY:
1717 do_statusbar_end();
1718 break;
1719 case NANO_FORWARD_KEY:
1720 do_statusbar_right();
1721 break;
1722 case NANO_BACK_KEY:
1723 do_statusbar_left();
1724 break;
1725 case NANO_BACKSPACE_KEY:
1726 /* If we're using restricted mode, the filename
1727 * isn't blank, and we're at the "Write File"
1728 * prompt, disable Backspace. */
1729 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1730 currshortcut != writefile_list)
1731 do_statusbar_backspace();
1732 break;
1733 case NANO_DELETE_KEY:
1734 /* If we're using restricted mode, the filename
1735 * isn't blank, and we're at the "Write File"
1736 * prompt, disable Delete. */
1737 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1738 currshortcut != writefile_list)
1739 do_statusbar_delete();
1740 break;
1741 case NANO_CUT_KEY:
1742 /* If we're using restricted mode, the filename
1743 * isn't blank, and we're at the "Write File"
1744 * prompt, disable Cut. */
1745 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1746 currshortcut != writefile_list)
1747 do_statusbar_cut_text();
1748 break;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001749 case NANO_VERBATIM_KEY:
1750 if (*meta_key == TRUE) {
1751 /* If we're using restricted mode, the filename
1752 * isn't blank, and we're at the "Write File"
1753 * prompt, disable verbatim input. */
1754 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001755 currshortcut != writefile_list) {
1756 bool got_enter;
1757 /* Whether we got the Enter key. */
1758
1759 do_statusbar_verbatim_input(&got_enter);
1760
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001761 /* If we got the Enter key, set input to the
1762 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001763 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001764 if (got_enter) {
1765 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001766 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001767 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001768 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001769 break;
1770 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001771 /* Handle the normal statusbar prompt shortcuts, setting
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001772 * ran_func to TRUE if we try to run their associated
1773 * functions and setting finished to TRUE to indicate
1774 * that we're done after trying to run their associated
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001775 * functions. */
1776 default:
1777 if (s->func != NULL) {
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001778 *ran_func = TRUE;
1779 if (!ISSET(VIEW_MODE) || s->viewok)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001780 s->func();
1781 }
1782 *finished = TRUE;
1783 }
1784 }
1785 }
1786
1787 return input;
1788}
1789
1790#ifndef DISABLE_MOUSE
1791bool do_statusbar_mouse(void)
1792{
1793 /* FIXME: If we clicked on a location in the statusbar, the cursor
1794 * should move to the location we clicked on. This functionality
1795 * should be in this function. */
1796 int mouse_x, mouse_y;
1797 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1798}
1799#endif
1800
1801void do_statusbar_home(void)
1802{
1803#ifndef NANO_SMALL
1804 if (ISSET(SMART_HOME)) {
1805 size_t statusbar_x_save = statusbar_x;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001806 char *blank_mb = charalloc(mb_cur_max());
1807 int blank_mb_len;
1808
1809 statusbar_x = 0;
1810
1811 while (statusbar_x < statusbar_xend) {
1812 blank_mb_len = parse_mbchar(answer + statusbar_x,
1813 blank_mb
1814#ifdef NANO_WIDE
1815 , NULL
1816#endif
1817 , NULL);
1818
1819 if (!is_blank_mbchar(blank_mb))
1820 break;
1821
1822 statusbar_x += blank_mb_len;
1823 }
1824
1825 free(blank_mb);
1826
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001827 if (statusbar_x == statusbar_x_save ||
1828 statusbar_x == statusbar_xend)
1829 statusbar_x = 0;
1830 } else
1831#endif
1832 statusbar_x = 0;
1833}
1834
1835void do_statusbar_end(void)
1836{
1837 statusbar_x = statusbar_xend;
1838}
1839
1840void do_statusbar_right(void)
1841{
1842 if (statusbar_x < statusbar_xend)
1843 statusbar_x = move_right(answer, statusbar_x);
1844}
1845
1846void do_statusbar_left(void)
1847{
1848 if (statusbar_x > 0)
1849 statusbar_x = move_left(answer, statusbar_x);
1850}
1851
1852void do_statusbar_backspace(void)
1853{
1854 if (statusbar_x > 0) {
1855 do_statusbar_left();
1856 do_statusbar_delete();
1857 }
1858}
1859
1860void do_statusbar_delete(void)
1861{
1862 if (statusbar_x < statusbar_xend) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001863 int char_buf_len = parse_mbchar(answer + statusbar_x, NULL
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001864#ifdef NANO_WIDE
1865 , NULL
1866#endif
David Lawrence Ramseyd96851f2005-01-07 22:39:43 +00001867 , 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{
1878 null_at(&answer, 0);
1879 statusbar_x = 0;
1880 statusbar_xend = 0;
1881}
1882
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001883void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001884{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001885 int *kbinput;
1886 size_t kbinput_len, i;
1887 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001888
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001889 *got_enter = FALSE;
1890
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001891 /* Read in all the verbatim characters. */
1892 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
1893
1894 /* Display all the verbatim characters at once. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001895 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001896
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001897 for (i = 0; i < kbinput_len; i++)
1898 output[i] = (char)kbinput[i];
1899 output[i] = '\0';
1900
1901 do_statusbar_output(output, kbinput_len, got_enter);
1902
1903 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001904}
1905
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001906void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001907 *got_enter)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001908{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001909 size_t i = 0;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001910
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001911 char *char_buf = charalloc(mb_cur_max());
1912 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001913
1914 assert(answer != NULL);
1915
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001916 *got_enter = FALSE;
1917
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001918 while (i < output_len) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001919 /* Null to newline, if needed. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001920 if (output[i] == '\0')
1921 output[i] = '\n';
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001922 /* Newline to Enter, if needed. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001923 else if (output[i] == '\n') {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001924 /* Set got_enter to TRUE to indicate that we got the Enter
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001925 * key, put back the rest of the characters in output so
1926 * that they can be parsed and output again, and get out. */
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001927 *got_enter = TRUE;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001928 unparse_kbinput(output + i, output_len - i);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001929 return;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001930 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001931
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001932 /* Interpret the next multibyte character. If it's an invalid
1933 * multibyte character, interpret it as though it's a byte
1934 * character. */
1935 char_buf_len = parse_mbchar(output + i, char_buf
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001936#ifdef NANO_WIDE
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001937 , NULL
1938#endif
1939 , NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001940
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001941 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001942
1943 /* More dangerousness fun =) */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001944 answer = charealloc(answer, statusbar_xend + char_buf_len + 1);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001945
1946 assert(statusbar_x <= statusbar_xend);
1947
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001948 charmove(&answer[statusbar_x + char_buf_len],
1949 &answer[statusbar_x], statusbar_xend - statusbar_x +
1950 char_buf_len);
1951 charcpy(&answer[statusbar_x], char_buf, char_buf_len);
1952 statusbar_xend += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001953
1954 do_statusbar_right();
1955 }
1956
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001957 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001958}
1959
Chris Allegretta6df90f52002-07-19 01:08:59 +00001960/* Return the placewewant associated with current_x. That is, xplustabs
1961 * is the zero-based column position of the cursor. Value is no smaller
1962 * than current_x. */
1963size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001964{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001965 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001966}
1967
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001968/* actual_x() gives the index in str of the character displayed at
1969 * column xplus. That is, actual_x() is the largest value such that
1970 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
1971size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001972{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001973 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00001974 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001975 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00001976 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001977
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001978 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001979
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001980 while (*str != '\0') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001981 int str_len = parse_mbchar(str, NULL
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001982#ifdef NANO_WIDE
1983 , NULL
1984#endif
David Lawrence Ramseyd96851f2005-01-07 22:39:43 +00001985 , &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001986
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001987 if (length > xplus)
1988 break;
1989
1990 i += str_len;
1991 str += str_len;
1992 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001993
Chris Allegretta6df90f52002-07-19 01:08:59 +00001994 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00001995}
1996
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00001997/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001998 * columns wide are the first size characters of str? */
1999size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002000{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002001 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002002 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002003
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002004 if (size == 0)
2005 return 0;
2006
2007 assert(str != NULL);
2008
2009 while (*str != '\0') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002010 int str_len = parse_mbchar(str, NULL
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002011#ifdef NANO_WIDE
2012 , NULL
2013#endif
David Lawrence Ramseyd96851f2005-01-07 22:39:43 +00002014 , &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002015
2016 str += str_len;
2017
2018 if (size <= str_len)
2019 break;
2020
2021 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002022 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002023
Chris Allegretta6df90f52002-07-19 01:08:59 +00002024 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002025}
2026
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002027/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002028size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002029{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002030 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002031}
2032
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002033void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002034{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002035 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002036}
2037
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002038void blank_edit(void)
2039{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002040 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002041 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002042 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002043}
2044
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002045void blank_statusbar(void)
2046{
2047 mvwaddstr(bottomwin, 0, 0, hblank);
2048}
2049
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002050void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002051{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002052 if (statusblank > 1)
2053 statusblank--;
2054 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
2055 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002056 blank_statusbar();
2057 wnoutrefresh(bottomwin);
2058 reset_cursor();
2059 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002060 }
2061}
2062
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002063void blank_bottombars(void)
2064{
2065 if (!ISSET(NO_HELP)) {
2066 mvwaddstr(bottomwin, 1, 0, hblank);
2067 mvwaddstr(bottomwin, 2, 0, hblank);
2068 }
2069}
2070
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002071/* Convert buf into a string that can be displayed on screen. The
2072 * caller wants to display buf starting with column start_col, and
2073 * extending for at most len columns. start_col is zero-based. len is
2074 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002075 * string is dynamically allocated, and should be freed. If dollars is
2076 * TRUE, the caller might put "$" at the beginning or end of the line if
2077 * it's too long. */
2078char *display_string(const char *buf, size_t start_col, size_t len, bool
2079 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002080{
2081 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002082 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002083 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002084 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002085 size_t alloc_len;
2086 /* The length of memory allocated for converted. */
2087 char *converted;
2088 /* The string we return. */
2089 size_t index;
2090 /* Current position in converted. */
2091
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002092 char *buf_mb = charalloc(mb_cur_max());
2093 int buf_mb_len;
2094#ifdef NANO_WIDE
2095 bool bad_char;
2096#endif
2097
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002098 /* If dollars is TRUE, make room for the "$" at the end of the
2099 * line. */
2100 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2101 len--;
2102
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002103 if (len == 0)
2104 return mallocstrcpy(NULL, "");
2105
2106 start_index = actual_x(buf, start_col);
2107 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002108
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002109 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002110
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002111 /* Allocate enough space for the entire line. It should contain
2112 * (len + 2) multibyte characters at most. */
2113 alloc_len = mb_cur_max() * (len + 2);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002114
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002115 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002116 index = 0;
2117
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002118 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002119 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002120 /* We don't display all of buf[start_index] since it starts to
2121 * the left of the screen. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002122 buf_mb_len = parse_mbchar(buf + start_index, buf_mb
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002123#ifdef NANO_WIDE
2124 , NULL
2125#endif
David Lawrence Ramseyd96851f2005-01-07 22:39:43 +00002126 , NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002127
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002128 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002129 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002130 char *ctrl_buf_mb = charalloc(mb_cur_max());
2131 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002132
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002133 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2134 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002135
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002136 for (i = 0; i < ctrl_buf_mb_len; i++)
2137 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002138
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002139 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002140
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002141 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002142
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002143 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002144 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002145 }
2146#ifdef NANO_WIDE
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002147 else if (mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002148 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002149 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002150
2151 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002152 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002153#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002154 }
2155
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002156 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002157 buf_mb_len = parse_mbchar(buf + start_index, buf_mb
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002158#ifdef NANO_WIDE
2159 , &bad_char
2160#endif
David Lawrence Ramseyd96851f2005-01-07 22:39:43 +00002161 , NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002162
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002163 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002164 converted[index++] =
2165#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2166 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
2167#endif
2168 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002169 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002170 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002171 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002172 start_col++;
2173 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002174 /* If buf contains a control character, interpret it. If it
2175 * contains an invalid multibyte control character, interpret
2176 * that character as though it's a normal control character. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002177 } else if (is_cntrl_mbchar(buf_mb)) {
2178 char *ctrl_buf_mb = charalloc(mb_cur_max());
2179 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002180
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002181 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002182 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002183
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002184 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2185 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002186
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002187 for (i = 0; i < ctrl_buf_mb_len; i++)
2188 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002189
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002190 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002191
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002192 free(ctrl_buf_mb);
2193 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002194 converted[index++] =
2195#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2196 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
2197#endif
2198 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002199 start_col++;
2200 } else {
2201 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002202
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002203#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002204 /* If buf contains an invalid multibyte non-control
2205 * character, interpret that character as though it's a
2206 * normal non-control character. */
2207 if (!ISSET(NO_UTF8) && bad_char) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002208 char *bad_buf_mb = charalloc(mb_cur_max());
2209 int bad_buf_mb_len;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002210
David Lawrence Ramsey4c6956b2005-01-12 04:32:43 +00002211 bad_buf_mb = make_mbchar((unsigned char)*buf_mb,
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002212 bad_buf_mb, &bad_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002213
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002214 for (i = 0; i < bad_buf_mb_len; i++)
2215 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002216
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002217 start_col += mbwidth(bad_buf_mb);
2218
2219 free(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002220 } else {
2221#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002222 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002223 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002224
2225 start_col += mbwidth(buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002226#ifdef NANO_WIDE
2227 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002228#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002229 }
2230
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002231 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002232 }
2233
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002234 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002235 converted[index] = '\0';
2236
2237 /* Make sure converted takes up no more than len columns. */
2238 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002239 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002240
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002241 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002242}
2243
Chris Allegretta7662c862003-01-13 01:35:15 +00002244/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002245 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002246 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002247 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002248 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002249void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002250{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002251 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002252 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002253
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002254 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002255
Chris Allegrettab3655b42001-10-22 03:15:31 +00002256 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002257 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002258
Chris Allegretta6df90f52002-07-19 01:08:59 +00002259 mvwaddstr(bottomwin, 0, 0, buf);
2260 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002261
2262 if (COLS > 1)
2263 waddch(bottomwin, x_real < wid ? ' ' : '$');
2264 if (COLS > 2) {
2265 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002266 char *expanded = display_string(inputbuf, page_start, wid,
2267 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002268
2269 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002270 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002271
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002272 waddstr(bottomwin, expanded);
2273 free(expanded);
2274 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2275 } else
2276 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002277 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002278}
2279
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002280/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002281 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002282int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002283#ifndef NANO_SMALL
2284 historyheadtype *history_list,
2285#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002286 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002287#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002288 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002289#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002290 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002291{
2292 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002293 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002294 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002295 /* used by input_tab() */
Chris Allegretta598106e2002-01-19 01:59:37 +00002296
Chris Allegretta5beed502003-01-05 20:41:21 +00002297#ifndef NANO_SMALL
2298 /* for history */
2299 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00002300 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00002301 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002302 int last_kbinput = 0;
2303
2304 /* This variable is used in the search history code. use_cb == 0
2305 means that we're using the existing history and ignoring
2306 currentbuf. use_cb == 1 means that the entry in answer should be
2307 moved to currentbuf or restored from currentbuf to answer.
2308 use_cb == 2 means that the entry in currentbuf should be moved to
2309 answer or restored from answer to currentbuf. */
2310 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002311#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002312 statusbar_xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002313
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002314 /* Only put statusbar_x at the end of the string if it's
2315 * uninitialized, if it would be past the end of the string as it
2316 * is, or if resetstatuspos is TRUE. Otherwise, leave it alone.
2317 * This is so the cursor position stays at the same place if a
2318 * prompt-changing toggle is pressed. */
2319 if (statusbar_x == (size_t)-1 || statusbar_x > statusbar_xend ||
2320 resetstatuspos)
2321 statusbar_x = statusbar_xend;
Chris Allegretta09fc4302003-01-16 22:16:38 +00002322
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002323 answer = charealloc(answer, statusbar_xend + 1);
2324 if (statusbar_xend > 0)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002325 strcpy(answer, def);
2326 else
2327 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002328
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002329 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002330
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002331 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00002332
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002333 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002334
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002335 /* Refresh the edit window before getting input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002336 wnoutrefresh(edit);
2337 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002338
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002339 /* If we're using restricted mode, we aren't allowed to change the
2340 * name of a file once it has one because that would allow writing
2341 * to files not specified on the command line. In this case,
2342 * disable all keys that would change the text if the filename isn't
2343 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002344 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002345 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002346 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002347
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002348 /* If we have a shortcut with an associated function, break out
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002349 * if we're finished after running or trying to run the
2350 * function. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002351 if (finished)
2352 break;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002353
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002354 assert(statusbar_x <= statusbar_xend &&
2355 statusbar_xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002356
Chris Allegretta04d848e2000-11-05 17:54:41 +00002357 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002358 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00002359
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002360 switch (kbinput) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002361 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002362#ifndef NANO_SMALL
2363 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00002364 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002365 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002366 history_list->current = (historytype *)history_list;
2367 history_list->len = strlen(answer);
2368 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002369
Chris Allegretta7662c862003-01-13 01:35:15 +00002370 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002371 complete = get_history_completion(history_list, answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002372 statusbar_x = strlen(complete);
2373 statusbar_xend = statusbar_x;
Chris Allegretta5beed502003-01-05 20:41:21 +00002374 answer = mallocstrcpy(answer, complete);
2375 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002376 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002377#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002378 else
2379#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002380#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002381#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002382 if (allow_tabs) {
Chris Allegretta327abda2003-01-17 05:04:17 +00002383 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002384
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002385 answer = input_tab(answer, statusbar_x, &tabbed, &shift,
2386 list);
2387 statusbar_xend = strlen(answer);
2388 statusbar_x += shift;
2389 if (statusbar_x > statusbar_xend)
2390 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002391 }
2392#endif
2393 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002394 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002395#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002396 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002397
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002398 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2399 isn't NULL, and currentbuf is different from answer,
2400 it means that we're scrolling up at the top of the
2401 search history, and we need to save the current
2402 answer in currentbuf; do this and reset use_cb to
2403 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002404 if (currentbuf == NULL || (use_cb == 1 &&
2405 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002406 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002407 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002408 }
2409
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002410 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2411 is different from answer, it means that we're
2412 scrolling up at the bottom of the search history, and
2413 we need to make the string in currentbuf the current
2414 answer; do this, blow away currentbuf since we don't
2415 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002416 if (currentbuf != NULL && use_cb == 2 &&
2417 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002418 answer = mallocstrcpy(answer, currentbuf);
2419 free(currentbuf);
2420 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002421 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002422 use_cb = 0;
2423
2424 /* else get older search from the history list and save
2425 it in answer; if there is no older search, blank out
2426 answer */
2427 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002428 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002429 statusbar_xend = strlen(history);
Chris Allegretta5beed502003-01-05 20:41:21 +00002430 } else {
2431 answer = mallocstrcpy(answer, "");
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002432 statusbar_xend = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002433 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002434 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002435 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002436#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002437 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002438 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002439#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002440 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002441
2442 /* get newer search from the history list and save it
2443 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002444 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002445 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002446 statusbar_xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002447
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002448 /* if there is no newer search, we're here */
2449
2450 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2451 that we're scrolling down at the bottom of the search
2452 history and we need to make the string in currentbuf
2453 the current answer; do this, blow away currentbuf
2454 since we don't need it anymore, and set use_cb to
2455 1 */
2456 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002457 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002458 free(currentbuf);
2459 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002460 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002461 use_cb = 1;
2462
2463 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2464 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002465 the search history and the current answer (if it's
2466 not blank) needs to be saved in currentbuf; do this,
2467 blank out answer (if necessary), and set use_cb to
2468 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002469 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002470 if (answer[0] != '\0') {
2471 currentbuf = mallocstrcpy(currentbuf, answer);
2472 answer = mallocstrcpy(answer, "");
2473 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002474 statusbar_xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002475 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002476 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002477 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002478 }
2479#endif
2480 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002481 }
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002482#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002483 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002484#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002485 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002486 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002487 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002488
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002489 /* We finished putting in an answer or ran a normal shortcut's
2490 * associated function, so reset statusbar_x. */
2491 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
2492 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002493 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002494
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002495 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002496}
2497
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002498/* Ask a question on the statusbar. Answer will be stored in answer
2499 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2500 * otherwise, the valid shortcut key caught. def is any editable text
2501 * we want to put up by default.
2502 *
2503 * New arg tabs tells whether or not to allow tab completion. */
2504int statusq(bool allow_tabs, const shortcut *s, const char *def,
2505#ifndef NANO_SMALL
2506 historyheadtype *which_history,
2507#endif
2508 const char *msg, ...)
2509{
2510 va_list ap;
2511 char *foo = charalloc(COLS - 3);
2512 int ret;
2513#ifndef DISABLE_TABCOMP
2514 bool list = FALSE;
2515#endif
2516
2517 bottombars(s);
2518
2519 va_start(ap, msg);
2520 vsnprintf(foo, COLS - 4, msg, ap);
2521 va_end(ap);
2522 foo[COLS - 4] = '\0';
2523
2524 ret = nanogetstr(allow_tabs, foo, def,
2525#ifndef NANO_SMALL
2526 which_history,
2527#endif
2528 s
2529#ifndef DISABLE_TABCOMP
2530 , &list
2531#endif
2532 );
2533 free(foo);
2534 resetstatuspos = FALSE;
2535
2536 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002537 case NANO_CANCEL_KEY:
2538 ret = -1;
2539 resetstatuspos = TRUE;
2540 break;
2541 case NANO_ENTER_KEY:
2542 ret = (answer[0] == '\0') ? -2 : 0;
2543 resetstatuspos = TRUE;
2544 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002545 }
2546 blank_statusbar();
2547
2548#ifdef DEBUG
2549 fprintf(stderr, "I got \"%s\"\n", answer);
2550#endif
2551
2552#ifndef DISABLE_TABCOMP
2553 /* if we've done tab completion, there might be a list of
2554 filename matches on the edit window at this point; make sure
2555 they're cleared off. */
2556 if (list)
2557 edit_refresh();
2558#endif
2559
2560 return ret;
2561}
2562
2563void statusq_abort(void)
2564{
2565 resetstatuspos = TRUE;
2566}
2567
Chris Allegrettaf717f982003-02-13 22:25:01 +00002568void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002569{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002570 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002571 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002572 size_t verlen = strlenpt(VERMSG) + 1;
2573 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002574 const char *prefix;
2575 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2576 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002577 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002578 const char *state;
2579 /* "Modified", "View", or spaces the length of "Modified".
2580 * Tells the state of this buffer. */
2581 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002582 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002583 char *exppath = NULL;
2584 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002585 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002586 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002587 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002588 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002589
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002590 assert(path != NULL || filename != NULL);
2591 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002592
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002593 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002594
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002595 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002596
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002597 if (COLS <= 5 || COLS - 5 < verlen)
2598 space = 0;
2599 else {
2600 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002601 /* Reserve 2/3 of the screen plus one column for after the
2602 * version message. */
2603 if (space < COLS - (COLS / 3) + 1)
2604 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002605 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002606
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002607 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002608 /* The version message should only take up 1/3 of the screen
2609 * minus one column. */
2610 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002611 waddstr(topwin, " ");
2612 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002613
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002614 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002615 state = _("Modified");
2616 else if (path == NULL && ISSET(VIEW_MODE))
2617 state = _("View");
2618 else {
2619 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002620 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002621 state = &hblank[COLS - statelen];
2622 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002623 statelen = strnlenpt(state, COLS);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002624 /* We need a space before state. */
2625 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2626 statelen++;
2627
2628 assert(space >= 0);
2629 if (space == 0 || statelen >= space)
2630 goto the_end;
2631
2632#ifndef DISABLE_BROWSER
2633 if (path != NULL)
2634 prefix = _("DIR:");
2635 else
2636#endif
2637 if (filename[0] == '\0') {
2638 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002639 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002640 } else
2641 prefix = _("File:");
2642 assert(statelen < space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002643 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002644 /* If newfie is FALSE, we need a space after prefix. */
2645 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002646 prefixlen++;
2647
2648 if (path == NULL)
2649 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002650 if (space >= prefixlen + statelen)
2651 space -= prefixlen + statelen;
2652 else
2653 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002654 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002655 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002656 size_t lenpt = strlenpt(path), start_col;
2657
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002658 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002659
2660 if (dots) {
2661 start_col = lenpt - space + 3;
2662 space -= 3;
2663 } else
2664 start_col = 0;
2665
2666 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002667 }
2668
2669 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002670 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2671 /* The length of the expanded filename. */
2672
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002673 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002674 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002675 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002676 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002677 assert(strlenpt(prefix) + 1 == prefixlen);
2678
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002679 waddch(topwin, ' ');
2680 waddstr(topwin, exppath);
2681 }
2682 } else {
2683 /* We will say something like "File: ...ename". */
2684 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002685 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002686 goto the_end;
2687 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002688 waddnstr(topwin, "...", space + 3);
2689 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002690 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002691 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002692 }
2693
2694 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002695 free(exppath);
2696
2697 if (COLS <= 1 || statelen >= COLS - 1)
2698 mvwaddnstr(topwin, 0, 0, state, COLS);
2699 else {
2700 assert(COLS - statelen - 2 >= 0);
2701 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2702 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2703 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002704
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002705 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002706
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002707 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002708 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002709 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002710}
2711
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002712/* If modified is not already set, set it and update titlebar. */
2713void set_modified(void)
2714{
2715 if (!ISSET(MODIFIED)) {
2716 SET(MODIFIED);
2717 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002718 }
2719}
2720
2721void statusbar(const char *msg, ...)
2722{
2723 va_list ap;
2724
2725 va_start(ap, msg);
2726
2727 /* Curses mode is turned off. If we use wmove() now, it will muck
2728 * up the terminal settings. So we just use vfprintf(). */
2729 if (curses_ended) {
2730 vfprintf(stderr, msg, ap);
2731 va_end(ap);
2732 return;
2733 }
2734
2735 /* Blank out the line. */
2736 blank_statusbar();
2737
2738 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002739 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002740 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002741#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002742 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002743
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002744 UNSET(WHITESPACE_DISPLAY);
2745#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002746 bar = charalloc(COLS - 3);
2747 vsnprintf(bar, COLS - 3, msg, ap);
2748 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002749 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002750#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2751 if (old_whitespace)
2752 SET(WHITESPACE_DISPLAY);
2753#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002754 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002755 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002756 start_x = (COLS - foo_len - 4) / 2;
2757
2758 wmove(bottomwin, 0, start_x);
2759 wattron(bottomwin, A_REVERSE);
2760
2761 waddstr(bottomwin, "[ ");
2762 waddstr(bottomwin, foo);
2763 free(foo);
2764 waddstr(bottomwin, " ]");
2765 wattroff(bottomwin, A_REVERSE);
2766 wnoutrefresh(bottomwin);
2767 reset_cursor();
2768 wrefresh(edit);
2769 /* Leave the cursor at its position in the edit window, not
2770 * in the statusbar. */
2771 }
2772
2773 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002774 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002775}
2776
Chris Allegretta6232d662002-05-12 19:52:15 +00002777void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002778{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002779 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002780
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002781 if (ISSET(NO_HELP))
2782 return;
2783
Chris Allegretta6232d662002-05-12 19:52:15 +00002784 if (s == main_list) {
2785 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002786 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002787 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002788 slen = length_of_list(s);
2789
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002790 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002791 if (slen > MAIN_VISIBLE)
2792 slen = MAIN_VISIBLE;
2793 }
2794
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002795 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002796 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002797 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002798
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002799 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002800
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002801 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002802 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002803
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002804 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002805#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002806 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002807 keystr = _("Up");
2808 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002809#endif
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00002810 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002811
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002812 if (s->ctrlval == NANO_CONTROL_SPACE)
2813 strcpy(foo, "^ ");
2814 else if (s->ctrlval == NANO_CONTROL_8)
2815 strcpy(foo, "^?");
2816 /* Normal values. Assume that the shortcut has an
2817 * equivalent control key, meta key sequence, or both. */
2818 else if (s->ctrlval != NANO_NO_KEY)
2819 sprintf(foo, "^%c", s->ctrlval + 64);
2820 else if (s->metaval != NANO_NO_KEY)
2821 sprintf(foo, "M-%c", toupper(s->metaval));
2822
2823 keystr = foo;
2824#ifndef NANO_SMALL
2825 }
2826#endif
2827
2828 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002829 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002830 }
2831
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002832 wnoutrefresh(bottomwin);
2833 reset_cursor();
2834 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002835}
2836
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002837/* Write a shortcut key to the help area at the bottom of the window.
2838 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2839 * to write at most len characters, even if len is very small and
2840 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2841 * the whole string! We do not bother padding the entry with blanks. */
2842void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002843{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002844 size_t keystroke_len = strlenpt(keystroke) + 1;
2845
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002846 assert(keystroke != NULL && desc != NULL);
2847
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002848 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002849 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002850 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002851
2852 if (len > keystroke_len)
2853 len -= keystroke_len;
2854 else
2855 len = 0;
2856
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002857 if (len > 0) {
2858 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002859 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002860 }
2861}
2862
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002863/* And so start the display update routines. */
2864
2865#ifndef NDEBUG
2866int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002867{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002868 int check_line = 0;
2869 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002870
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002871 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
2872 check_line++;
2873 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002874}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002875#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00002876
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002877/* nano scrolls horizontally within a line in chunks. This function
2878 * returns the column number of the first character displayed in the
2879 * window when the cursor is at the given column. Note that
2880 * 0 <= column - get_page_start(column) < COLS. */
2881size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002882{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002883 assert(COLS > 0);
2884 if (column == 0 || column < COLS - 1)
2885 return 0;
2886 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002887 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002888 else if (COLS > 2)
2889 return column - (COLS - 2);
2890 else
2891 return column - (COLS - 1);
2892 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002893}
2894
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002895/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002896 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002897void reset_cursor(void)
2898{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002899 /* If we haven't opened any files yet, put the cursor in the top
2900 * left corner of the edit window and get out. */
2901 if (edittop == NULL || current == NULL) {
2902 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002903 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002904 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002905
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002906 current_y = current->lineno - edittop->lineno;
2907 if (current_y < editwinrows) {
2908 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002909 wmove(edit, current_y, x - get_page_start(x));
2910 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002911}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002912
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002913/* edit_add() takes care of the job of actually painting a line into the
2914 * edit window. fileptr is the line to be painted, at row yval of the
2915 * window. converted is the actual string to be written to the window,
2916 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00002917 * characters. start is the column number of the first character of
2918 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002919 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002920void edit_add(const filestruct *fileptr, const char *converted, int
2921 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002922{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002923#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
2924 size_t startpos = actual_x(fileptr->data, start);
2925 /* The position in fileptr->data of the leftmost character
2926 * that displays at least partially on the window. */
2927 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2928 /* The position in fileptr->data of the first character that is
2929 * completely off the window to the right.
2930 *
2931 * Note that endpos might be beyond the null terminator of the
2932 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002933#endif
2934
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002935 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002936 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002937
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002938 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002939 * just the text that needs it). */
2940 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002941
Chris Allegretta7dd77682001-12-08 19:52:28 +00002942#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00002943 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002944 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002945
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002946 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2947 int x_start;
2948 /* Starting column for mvwaddnstr. Zero-based. */
2949 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002950 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002951 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00002952 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002953 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002954 regmatch_t startmatch; /* match position for start_regexp */
2955 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002956
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002957 if (tmpcolor->bright)
2958 wattron(edit, A_BOLD);
2959 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002960 /* Two notes about regexec(). Return value 0 means there is
2961 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002962 * after the match. */
2963
2964 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002965 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002966 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002967
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002968 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002969 * last match. Even though two matches may overlap, we
2970 * want to ignore them, so that we can highlight
2971 * C-strings correctly. */
2972 while (k < endpos) {
2973 /* Note the fifth parameter to regexec(). It says
2974 * not to match the beginning-of-line character
2975 * unless k is 0. If regexec() returns REG_NOMATCH,
2976 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00002977 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002978 &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002979 break;
2980 /* Translate the match to the beginning of the line. */
2981 startmatch.rm_so += k;
2982 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002983 if (startmatch.rm_so == startmatch.rm_eo) {
2984 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00002985 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002986 } else if (startmatch.rm_so < endpos &&
2987 startmatch.rm_eo > startpos) {
2988 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002989 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002990 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002991 x_start = strnlenpt(fileptr->data,
2992 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002993
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002994 index = actual_x(converted, x_start);
2995
2996 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00002997 strnlenpt(fileptr->data,
2998 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00002999
3000 assert(0 <= x_start && 0 <= paintlen);
3001
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003002 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003003 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003004 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003005 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003006 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003007 } else {
3008 /* This is a multi-line regexp. There are two steps.
3009 * First, we have to see if the beginning of the line is
3010 * colored by a start on an earlier line, and an end on
3011 * this line or later.
3012 *
3013 * We find the first line before fileptr matching the
3014 * start. If every match on that line is followed by an
3015 * end, then go to step two. Otherwise, find the next line
3016 * after start_line matching the end. If that line is not
3017 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003018
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003019 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003020 /* the first line before fileptr matching start */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003021 regoff_t start_col;
3022 /* where it starts in that line */
3023 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003024
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003025 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003026 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003027 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003028 /* If there is an end on this line, there is no need
3029 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003030 if (regexec(tmpcolor->end, start_line->data, 0,
3031 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003032 goto step_two;
3033 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003034 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003035 /* No start found, so skip to the next step. */
3036 if (start_line == NULL)
3037 goto step_two;
3038 /* Now start_line is the first line before fileptr
3039 * containing a start match. Is there a start on this
3040 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003041
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003042 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003043 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003044 start_col += startmatch.rm_so;
3045 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003046 if (regexec(tmpcolor->end,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003047 start_line->data + start_col + startmatch.rm_eo,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003048 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
3049 REG_NOTBOL) == REG_NOMATCH)
3050 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003051 break;
3052 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003053 if (regexec(&tmpcolor->start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003054 start_line->data + start_col, 1,
3055 &startmatch, REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003056 /* No later start on this line. */
3057 goto step_two;
3058 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003059 /* Indeed, there is a start not followed on this line by
3060 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003061
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003062 /* We have already checked that there is no end before
3063 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003064 * the start at all? We don't paint unterminated
3065 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003066 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003067 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003068 regexec(tmpcolor->end, end_line->data, 1,
3069 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003070 end_line = end_line->next;
3071
3072 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003073 if (end_line == NULL || (end_line == fileptr &&
3074 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003075 goto step_two;
3076
3077 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003078 if (end_line != fileptr)
3079 /* If the start of fileptr is on a different line
3080 * from the end, paintlen is -1, meaning that
3081 * everything on the line gets painted. */
3082 paintlen = -1;
3083 else
3084 /* Otherwise, paintlen is the expanded location of
3085 * the end of the match minus the expanded location
3086 * of the beginning of the page. */
3087 paintlen = actual_x(converted,
3088 strnlenpt(fileptr->data, endmatch.rm_eo) -
3089 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003090
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003091 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003092
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003093 step_two:
3094 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003095 start_col = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003096 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003097 if (regexec(&tmpcolor->start,
3098 fileptr->data + start_col, 1, &startmatch,
3099 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
3100 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003101 /* No more starts on this line. */
3102 break;
3103 /* Translate the match to be relative to the
3104 * beginning of the line. */
3105 startmatch.rm_so += start_col;
3106 startmatch.rm_eo += start_col;
3107
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003108 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003109 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003110 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003111 x_start = strnlenpt(fileptr->data,
3112 startmatch.rm_so) - start;
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003113 index = actual_x(converted, x_start);
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003114 if (regexec(tmpcolor->end,
3115 fileptr->data + startmatch.rm_eo, 1, &endmatch,
3116 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003117 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003118 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003119 endmatch.rm_so += startmatch.rm_eo;
3120 endmatch.rm_eo += startmatch.rm_eo;
3121 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003122 * appear on this page, and is the match more
3123 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003124 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003125 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003126 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003127 strnlenpt(fileptr->data,
3128 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003129
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003130 assert(0 <= x_start && x_start < COLS);
3131
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003132 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003133 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003134 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003135 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003136 /* There is no end on this line. But we haven't
3137 * yet looked for one on later lines. */
3138 end_line = fileptr->next;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003139 while (end_line != NULL &&
3140 regexec(tmpcolor->end, end_line->data, 0,
3141 NULL, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003142 end_line = end_line->next;
3143 if (end_line != NULL) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003144
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003145 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003146
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003147 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003148 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003149 /* We painted to the end of the line, so
3150 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003151 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003152 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003153 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003154 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003155 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003156 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003157
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003158 wattroff(edit, A_BOLD);
3159 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
3160 } /* for tmpcolor in colorstrings */
3161 }
Chris Allegretta598106e2002-01-19 01:59:37 +00003162#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003163
Chris Allegretta7dd77682001-12-08 19:52:28 +00003164#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003165 if (ISSET(MARK_ISSET)
3166 && (fileptr->lineno <= mark_beginbuf->lineno
3167 || fileptr->lineno <= current->lineno)
3168 && (fileptr->lineno >= mark_beginbuf->lineno
3169 || fileptr->lineno >= current->lineno)) {
3170 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003171
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003172 const filestruct *top;
3173 /* Either current or mark_beginbuf, whichever is first. */
3174 size_t top_x;
3175 /* current_x or mark_beginx, corresponding to top. */
3176 const filestruct *bot;
3177 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003178 int x_start;
3179 /* Starting column for mvwaddnstr. Zero-based. */
3180 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003181 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003182 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003183 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003184 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003185
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003186 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003187
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003188 if (top->lineno < fileptr->lineno || top_x < startpos)
3189 top_x = startpos;
3190 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3191 bot_x = endpos;
3192
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003193 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003194 if (top_x < endpos && bot_x > startpos) {
3195 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003196
3197 /* x_start is the expanded location of the beginning of the
3198 * mark minus the beginning of the page. */
3199 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003200
3201 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003202 /* If the end of the mark is off the page, paintlen is
3203 * -1, meaning that everything on the line gets
3204 * painted. */
3205 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003206 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003207 /* Otherwise, paintlen is the expanded location of the
3208 * end of the mark minus the expanded location of the
3209 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003210 paintlen = strnlenpt(fileptr->data, bot_x) -
3211 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003212
3213 /* If x_start is before the beginning of the page, shift
3214 * paintlen x_start characters to compensate, and put
3215 * x_start at the beginning of the page. */
3216 if (x_start < 0) {
3217 paintlen += x_start;
3218 x_start = 0;
3219 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003220
3221 assert(x_start >= 0 && x_start <= strlen(converted));
3222
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003223 index = actual_x(converted, x_start);
3224 if (paintlen > 0)
3225 paintlen = actual_x(converted + index, paintlen);
3226
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003227 wattron(edit, A_REVERSE);
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003228 mvwaddnstr(edit, yval, x_start, converted + x_start,
3229 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003230 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003231 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003232 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003233#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003234}
3235
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003236/* Just update one line in the edit buffer. This is basically a wrapper
3237 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003238 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003239 * If fileptr != current, then index is considered 0. The line will be
3240 * displayed starting with fileptr->data[index]. Likely args are
3241 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003242void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003243{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003244 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003245 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003246 char *converted;
3247 /* fileptr->data converted to have tabs and control characters
3248 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003249 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003250
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003251 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003252
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003253 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003254
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003255 /* We assume the line numbers are valid. Is that really true? */
3256 assert(line < 0 || line == check_linenumbers(fileptr));
3257
3258 if (line < 0 || line >= editwinrows)
3259 return;
3260
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003261 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003262 mvwaddstr(edit, line, 0, hblank);
3263
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003264 /* Next, convert variables that index the line to their equivalent
3265 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003266 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003267 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003268
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003269 /* Expand the line, replacing tabs with spaces, and control
3270 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003271 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003272
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003273 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003274 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003275 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003276
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003277 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003278 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003279 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003280 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003281}
3282
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003283/* Return a nonzero value if we need an update after moving
3284 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003285 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003286int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003287{
3288 return
3289#ifndef NANO_SMALL
3290 ISSET(MARK_ISSET) ||
3291#endif
3292 get_page_start(old_pww) != get_page_start(placewewant);
3293}
3294
3295/* Return a nonzero value if we need an update after moving vertically.
3296 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003297 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003298int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003299{
3300 return
3301#ifndef NANO_SMALL
3302 ISSET(MARK_ISSET) ||
3303#endif
3304 get_page_start(old_pww) != get_page_start(placewewant);
3305}
3306
3307/* Scroll the edit window in the given direction and the given number
3308 * of lines, and draw new lines on the blank lines left after the
3309 * scrolling. direction is the direction to scroll, either UP or DOWN,
3310 * and nlines is the number of lines to scroll. Don't redraw the old
3311 * topmost or bottommost line (where we assume current is) before
3312 * scrolling or draw the new topmost or bottommost line after scrolling
3313 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003314 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003315void edit_scroll(updown direction, int nlines)
3316{
3317 filestruct *foo;
3318 int i, scroll_rows = 0;
3319
3320 /* Scrolling less than one line or more than editwinrows lines is
3321 * redundant, so don't allow it. */
3322 if (nlines < 1 || nlines > editwinrows)
3323 return;
3324
3325 /* Move the top line of the edit window up or down (depending on the
3326 * value of direction) nlines lines. If there are fewer lines of
3327 * text than that left, move it to the top or bottom line of the
3328 * file (depending on the value of direction). Keep track of
3329 * how many lines we moved in scroll_rows. */
3330 for (i = nlines; i > 0; i--) {
3331 if (direction == UP) {
3332 if (edittop->prev == NULL)
3333 break;
3334 edittop = edittop->prev;
3335 scroll_rows--;
3336 } else {
3337 if (edittop->next == NULL)
3338 break;
3339 edittop = edittop->next;
3340 scroll_rows++;
3341 }
3342 }
3343
3344 /* Scroll the text on the screen up or down scroll_rows lines,
3345 * depending on the value of direction. */
3346 scrollok(edit, TRUE);
3347 wscrl(edit, scroll_rows);
3348 scrollok(edit, FALSE);
3349
3350 foo = edittop;
3351 if (direction != UP) {
3352 int slines = editwinrows - nlines;
3353 for (; slines > 0 && foo != NULL; slines--)
3354 foo = foo->next;
3355 }
3356
3357 /* And draw new lines on the blank top or bottom lines of the edit
3358 * window, depending on the value of direction. Don't draw the new
3359 * topmost or new bottommost line. */
3360 while (scroll_rows != 0 && foo != NULL) {
3361 if (foo->next != NULL)
3362 update_line(foo, 0);
3363 if (direction == UP)
3364 scroll_rows++;
3365 else
3366 scroll_rows--;
3367 foo = foo->next;
3368 }
3369}
3370
3371/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003372 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003373void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003374{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003375 int do_refresh = need_vertical_update(0) ||
3376 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003377 const filestruct *foo;
3378
3379 /* If either old_current or current is offscreen, refresh the screen
3380 * and get out. */
3381 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3382 edittop->lineno + editwinrows || current->lineno <
3383 edittop->lineno || current->lineno >= edittop->lineno +
3384 editwinrows) {
3385 edit_refresh();
3386 return;
3387 }
3388
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003389 /* Update old_current and current if we're not on the first page
3390 * and/or we're not on the same page as before. If the mark is on,
3391 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003392 foo = old_current;
3393 while (foo != current) {
3394 if (do_refresh)
3395 update_line(foo, 0);
3396#ifndef NANO_SMALL
3397 if (!ISSET(MARK_ISSET))
3398#endif
3399 break;
3400 if (foo->lineno > current->lineno)
3401 foo = foo->prev;
3402 else
3403 foo = foo->next;
3404 }
3405 if (do_refresh)
3406 update_line(current, current_x);
3407}
3408
Chris Allegretta6df90f52002-07-19 01:08:59 +00003409/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003410void edit_refresh(void)
3411{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003412 if (current->lineno < edittop->lineno ||
3413 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003414 /* Note that edit_update() changes edittop so that it's in range
3415 * of current. Thus, when it then calls edit_refresh(), there
3416 * is no danger of getting an infinite loop. */
3417 edit_update(
3418#ifndef NANO_SMALL
3419 ISSET(SMOOTHSCROLL) ? NONE :
3420#endif
3421 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003422 else {
3423 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003424 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003425
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003426#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003427 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003428#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003429
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003430 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003431 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003432 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003433 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003434 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003435 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003436 }
3437 while (nlines < editwinrows) {
3438 mvwaddstr(edit, nlines, 0, hblank);
3439 nlines++;
3440 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003441 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003442 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003443 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003444}
3445
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003446/* A nice generic routine to update the edit buffer. We keep current in
3447 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003448void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003449{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003450 filestruct *foo = current;
3451
Chris Allegretta6df90f52002-07-19 01:08:59 +00003452 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003453 /* If location is CENTER, we move edittop up (editwinrows / 2)
3454 * lines. This puts current at the center of the screen. If
3455 * location is NONE, we move edittop up current_y lines if
3456 * current_y is in range of the screen, 0 lines if current_y is
3457 * less than 0, or (editwinrows - 1) lines if current_y is
3458 * greater than (editwinrows - 1). This puts current at the
3459 * same place on the screen as before, or at the top or bottom
3460 * of the screen if edittop is beyond either. */
3461 int goal;
3462
3463 if (location == CENTER)
3464 goal = editwinrows / 2;
3465 else {
3466 goal = current_y;
3467
3468 /* Limit goal to (editwinrows - 1) lines maximum. */
3469 if (goal > editwinrows - 1)
3470 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003471 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003472
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003473 for (; goal > 0 && foo->prev != NULL; goal--)
3474 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003475 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003476
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003477 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003478 edit_refresh();
3479}
3480
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003481/* Ask a simple yes/no question, specified in msg, on the statusbar.
3482 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3483 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003484int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003485{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003486 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003487 const char *yesstr; /* String of yes characters accepted. */
3488 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003489 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003490
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003491 /* yesstr, nostr, and allstr are strings of any length. Each string
3492 * consists of all characters accepted as a valid character for that
3493 * value. The first value will be the one displayed in the
3494 * shortcuts. Translators: if possible, specify both the shortcuts
3495 * for your language and English. For example, in French: "OoYy"
3496 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003497 yesstr = _("Yy");
3498 nostr = _("Nn");
3499 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003500
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003501 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003502 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003503
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003504 if (COLS < 32)
3505 width = COLS / 2;
3506
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003507 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003508 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003509
Chris Allegretta6232d662002-05-12 19:52:15 +00003510 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003511 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003512 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003513
3514 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003515 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003516 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003517 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003518 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003519
Chris Allegrettadb28e962003-01-28 01:23:40 +00003520 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003521 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003522 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003523
Chris Allegrettadb28e962003-01-28 01:23:40 +00003524 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003525 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003526 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003527
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003528 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003529
3530 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003531 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003532
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003533 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003534
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003535 wrefresh(bottomwin);
3536
Chris Allegrettadb28e962003-01-28 01:23:40 +00003537 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003538 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003539 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003540#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003541 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003542#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003543
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003544 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003545
3546 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003547 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003548#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003549 /* Look, ma! We get to duplicate lots of code from
3550 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003551 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003552 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003553
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003554 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003555 wenclose(bottomwin, mouse_y, mouse_x) &&
3556 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003557 int x = mouse_x / width;
3558 /* Did we click in the first column of shortcuts, or
3559 * the second? */
3560 int y = mouse_y - editwinrows - 3;
3561 /* Did we click in the first row of shortcuts? */
3562
3563 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3564
3565 /* x = 0 means they clicked Yes or No.
3566 * y = 0 means Yes or All. */
3567 ok = -2 * x * y + x - y + 1;
3568
3569 if (ok == 2 && !all)
3570 ok = -2;
3571 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003572 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003573#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003574 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003575 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003576 else if (strchr(yesstr, kbinput) != NULL)
3577 ok = 1;
3578 else if (strchr(nostr, kbinput) != NULL)
3579 ok = 0;
3580 else if (all && strchr(allstr, kbinput) != NULL)
3581 ok = 2;
3582 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003583
Chris Allegrettadb28e962003-01-28 01:23:40 +00003584 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003585}
3586
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003587void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003588{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003589 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003590 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003591 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003592 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003593 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003594 wnoutrefresh(bottomwin);
3595 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003596 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003597 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003598 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003599 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003600 edit_refresh();
3601 /* FIXME: bottomwin needs to be refreshed too. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003602}
3603
3604void display_main_list(void)
3605{
3606 bottombars(main_list);
3607}
3608
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003609/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3610 * display the cursor position. Otherwise, we display it only if the
3611 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003612 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003613 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3614 * old_i and old_totsize. That way, we leave the current statusbar
3615 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003616void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003617{
Chris Allegrettad26ab912003-01-28 01:16:47 +00003618 const filestruct *fileptr;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003619 size_t i = 0;
3620 static size_t old_i = 0;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003621 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003622
Chris Allegrettad26ab912003-01-28 01:16:47 +00003623 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003624
3625 if (old_totsize == -1)
3626 old_totsize = totsize;
3627
Chris Allegrettad26ab912003-01-28 01:16:47 +00003628 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
3629 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003630 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003631 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003632 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003633
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003634 /* Check whether totsize is correct. Else there is a bug
3635 * somewhere. */
3636 assert(current != filebot || i == totsize);
3637
Chris Allegrettad26ab912003-01-28 01:16:47 +00003638 if (constant && ISSET(DISABLE_CURPOS)) {
3639 UNSET(DISABLE_CURPOS);
3640 old_i = i;
3641 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003642 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003643 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003644
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003645 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003646 * unconditionally; otherwise, only display the position when the
3647 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003648 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003649 size_t xpt = xplustabs() + 1;
3650 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003651 int linepct = 100 * current->lineno / totlines;
3652 int colpct = 100 * xpt / cur_len;
3653 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
3654
3655 statusbar(
3656 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3657 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003658 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003659 (unsigned long)i, totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003660 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003661 }
3662
3663 old_i = i;
3664 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003665}
3666
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003667void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003668{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003669 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003670}
3671
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003672#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003673/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003674int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003675{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003676 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003677
3678 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3679 ptr++;
3680 j++;
3681 }
3682 if (j == COLS - 5) {
3683 /* Don't wrap at the first of two spaces following a period. */
3684 if (*ptr == ' ' && *(ptr + 1) == ' ')
3685 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003686 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003687 while (*ptr != ' ' && j > 0) {
3688 ptr--;
3689 j--;
3690 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003691 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003692 if (j == 0)
3693 j = COLS - 5;
3694 }
3695 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
3696 return j;
3697}
3698
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003699/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003700void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003701{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003702 int line = 0;
3703 /* The line number in help_text of the first displayed help line.
3704 * This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003705 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003706 /* no_more means the end of the help text is shown, so don't go
3707 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003708 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003709 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003710
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003711 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003712#ifndef DISABLE_MOUSE
3713 const shortcut *oldshortcut = currshortcut;
3714 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003715 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003716#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003717
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003718 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003719 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003720 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003721 blank_statusbar();
3722
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003723 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003724 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003725 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003726
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003727#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003728 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003729 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003730 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003731#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003732
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003733 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003734 /* Make sure that the help screen's shortcut list will actually
3735 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003736 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003737 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003738 }
3739 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003740
3741 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003742 int i;
3743 int old_line = line;
3744 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003745 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003746
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003747 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003748#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003749 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003750 {
3751 int mouse_x, mouse_y;
3752 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3753 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003754 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003755#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003756 case NANO_NEXTPAGE_KEY:
3757 case NANO_NEXTPAGE_FKEY:
3758 if (!no_more)
3759 line += editwinrows - 2;
3760 break;
3761 case NANO_PREVPAGE_KEY:
3762 case NANO_PREVPAGE_FKEY:
3763 if (line > 0) {
3764 line -= editwinrows - 2;
3765 if (line < 0)
3766 line = 0;
3767 }
3768 break;
3769 case NANO_PREVLINE_KEY:
3770 if (line > 0)
3771 line--;
3772 break;
3773 case NANO_NEXTLINE_KEY:
3774 if (!no_more)
3775 line++;
3776 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003777 }
3778
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003779 if (line == old_line && kbinput != ERR)
3780 goto skip_redisplay;
3781
3782 blank_edit();
3783
3784 assert(COLS > 5);
3785
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003786 /* Calculate where in the text we should be, based on the
3787 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003788 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003789 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003790 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003791 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003792 }
3793
Chris Allegretta4640fe32003-02-10 03:10:03 +00003794 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003795 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003796
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003797 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003798 ptr += j;
3799 if (*ptr == '\n')
3800 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003801 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003802 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003803
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003804 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003805 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003806 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3807 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003808
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003809#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003810 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003811#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003812
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003813 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003814 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003815 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003816 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003817 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003818 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003819 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003820
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003821 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003822 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003823
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003824 /* The help_init() at the beginning allocated help_text. Since
3825 * help_text has now been written to the screen, we don't need it
3826 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003827 free(help_text);
3828 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003829}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003830#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003831
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003832/* Highlight the current word being replaced or spell checked. We
3833 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003834void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003835{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003836 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003837 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003838
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003839 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003840 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003841 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003842
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003843 assert(y > 0);
3844
3845 if (word_len > y)
3846 y--;
3847
Chris Allegrettafb62f732000-12-05 11:36:41 +00003848 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003849
Chris Allegrettafb62f732000-12-05 11:36:41 +00003850 if (highlight_flag)
3851 wattron(edit, A_REVERSE);
3852
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003853#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003854 /* This is so we can show zero-length regexes. */
3855 if (word_len == 0)
3856 waddstr(edit, " ");
3857 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003858#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003859 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003860
3861 if (word_len > y)
3862 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003863
3864 if (highlight_flag)
3865 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003866}
3867
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003868#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003869/* Dump the passed-in file structure to stderr. */
3870void dump_buffer(const filestruct *inptr)
3871{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003872 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003873 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003874 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003875 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003876 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003877 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003878
3879 while (inptr != NULL) {
3880 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
3881 inptr = inptr->next;
3882 }
3883}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003884
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003885/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00003886void dump_buffer_reverse(void)
3887{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003888 const filestruct *fileptr = filebot;
3889
3890 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00003891 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003892 fileptr = fileptr->prev;
3893 }
3894}
3895#endif /* DEBUG */
3896
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003897#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003898#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003899#define XLCREDIT_LEN 8
3900
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00003901/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003902void do_credits(void)
3903{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003904 int crpos = 0, xlpos = 0;
3905 const char *credits[CREDIT_LEN] = {
3906 NULL, /* "The nano text editor" */
3907 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003908 VERSION,
3909 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003910 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003911 "Chris Allegretta",
3912 "Jordi Mallach",
3913 "Adam Rogoyski",
3914 "Rob Siemborski",
3915 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003916 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003917 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00003918 "Ken Tyler",
3919 "Sven Guckes",
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003920#ifdef NANO_WIDE
David Lawrence Ramsey487d08c2005-01-12 18:16:17 +00003921 !ISSET(NO_UTF8) ? "Florian König" :
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003922#endif
3923 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00003924 "Pauli Virtanen",
3925 "Daniele Medri",
3926 "Clement Laforet",
3927 "Tedi Heriyanto",
3928 "Bill Soudan",
3929 "Christian Weisgerber",
3930 "Erik Andersen",
3931 "Big Gaute",
3932 "Joshua Jensen",
3933 "Ryan Krebs",
3934 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003935 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003936 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003937 "Plattsburgh State University",
3938 "Benet Laboratories",
3939 "Amy Allegretta",
3940 "Linda Young",
3941 "Jeremy Robichaud",
3942 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003943 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003944 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003945 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003946 "Thomas Dickey",
3947 "Pavel Curtis",
3948 "Zeyd Ben-Halim",
3949 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003950 NULL, /* "and anyone else we forgot..." */
3951 NULL, /* "Thank you for using nano!" */
3952 "",
3953 "",
3954 "",
3955 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00003956 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003957 "",
3958 "",
3959 "",
3960 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003961 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003962 };
3963
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003964 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003965 N_("The nano text editor"),
3966 N_("version"),
3967 N_("Brought to you by:"),
3968 N_("Special thanks to:"),
3969 N_("The Free Software Foundation"),
3970 N_("For ncurses:"),
3971 N_("and anyone else we forgot..."),
3972 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003973 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003974
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003975 curs_set(0);
3976 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003977 scrollok(edit, TRUE);
3978 blank_titlebar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003979 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003980 blank_statusbar();
3981 blank_bottombars();
3982 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003983 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003984 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003985
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003986 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
3987 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003988 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003989 if (crpos < CREDIT_LEN) {
3990 const char *what = credits[crpos];
3991 size_t start_x;
3992
3993 if (what == NULL) {
3994 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00003995 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003996 xlpos++;
3997 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003998 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramseyeb711b02004-12-05 22:24:39 +00003999 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x,
4000 what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004001 }
4002 napms(700);
4003 scroll(edit);
4004 wrefresh(edit);
4005 if (wgetch(edit) != ERR)
4006 break;
4007 napms(700);
4008 scroll(edit);
4009 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004010 }
4011
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004012 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004013 nodelay(edit, FALSE);
4014 curs_set(1);
4015 display_main_list();
4016 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004017}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004018#endif