blob: 131505de4b7a7c909e62b74cd69d62ac904787ab [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * winio.c *
4 * *
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00005 * Copyright (C) 1999-2005 Chris Allegretta *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00006 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
Jordi Mallach55381aa2004-11-17 23:17:05 +000022#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000025
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000026#include <stdarg.h>
27#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000028#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000029#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000030#include <ctype.h>
Chris Allegretta6232d662002-05-12 19:52:15 +000031#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000032#include "proto.h"
33#include "nano.h"
34
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +000035static int *key_buffer = NULL;
David Lawrence Ramsey74835712004-12-04 17:41:52 +000036 /* The default keystroke buffer,
37 * containing all the keystrokes we have
38 * at a given point. */
39static size_t key_buffer_len = 0;
40 /* The length of the default keystroke
41 * buffer. */
42static int statusblank = 0; /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000043 * we call statusbar(), before we
44 * actually blank the statusbar. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +000045static size_t statusbar_x = (size_t)-1;
46 /* The cursor position in answer. */
47static size_t statusbar_xend = 0;
48 /* The length of answer. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000049static bool resetstatuspos = FALSE;
50 /* Should we reset the cursor position
51 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000052
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000053/* Control character compatibility:
54 *
55 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
56 * VT100, and VT220.
57 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
58 * VT220, and VT320.
59 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
60 * VT220, and VT320.
61 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
62 * VT220, and VT320.
63 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
64 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000065 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000066 * ANSI, VT100, and VT220, and which is Backspace under VT320.
67 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000068 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000069 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
70 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000071 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000072 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000073 * on which the VT320 sequences are translated by the keypad to KEY_DC
74 * and [nothing]. We work around this conflict via the REBIND_DELETE
75 * flag: if it's not set, we assume VT320 compatibility, and if it is,
76 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
77 * Hemel for helping work this conflict out.
78 *
79 * Escape sequence compatibility:
80 *
81 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000082 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000083 * console), xterm, rxvt, and Eterm. Among these, there are several
84 * conflicts and omissions, outlined as follows:
85 *
86 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
87 * (Ctrl-I is also Tab on ANSI, which we already support.)
88 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
89 * NumLock off on Linux console; the latter is omitted. (The editing
90 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000091 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000092 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
93 * latter is omitted. (Mouse input will only work properly if the
94 * extended keypad value KEY_MOUSE is generated on mouse events
95 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000096 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000097 * omitted. (The editing keypad is more important to have working
98 * than the function keys, because the functions of the former are not
99 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000100 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000101 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000102 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000103 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000104 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
105 * omitted. (The arrow keys, with or without modifiers, are more
106 * important to have working than the function keys, because the
107 * functions of the former are not arbitrary and the functions of the
108 * latter are.)
109 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
110 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000111 *
112 * Note that Center (5) on the numeric keypad with NumLock off can also
113 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000114
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000115#ifndef NANO_SMALL
116/* Reset all the input routines that rely on character sequences. */
117void reset_kbinput(void)
118{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000119 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000120 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000121 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000122}
123#endif
124
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000125/* Read in a sequence of keystrokes from win and save them in the
126 * default keystroke buffer. This should only be called when the
127 * default keystroke buffer is empty. */
128void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000129{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000130 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000131
132 /* If the keystroke buffer isn't empty, get out. */
133 if (key_buffer != NULL)
134 return;
135
136 /* Read in the first character using blocking input. */
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000137#ifndef NANO_SMALL
138 allow_pending_sigwinch(TRUE);
139#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000140
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000141 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000142
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000143#ifndef NANO_SMALL
144 allow_pending_sigwinch(FALSE);
145#endif
146
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000147 /* Increment the length of the keystroke buffer, save the value of
148 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000149 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000150 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000151 key_buffer = (int *)nmalloc(sizeof(int));
152 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000153
154 /* Read in the remaining characters using non-blocking input. */
155 nodelay(win, TRUE);
156
157 while (TRUE) {
158#ifndef NANO_SMALL
159 allow_pending_sigwinch(TRUE);
160#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000161
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000162 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000163
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000164 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000165 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000166 break;
167
168 /* Otherwise, increment the length of the keystroke buffer, save
169 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000170 * if the keystroke is an extended keypad value or FALSE if it
171 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000172 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000173 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
174 sizeof(int));
175 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000176
177#ifndef NANO_SMALL
178 allow_pending_sigwinch(FALSE);
179#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000180 }
181
182 /* Switch back to non-blocking input. */
183 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000184}
185
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000186/* Return the length of the default keystroke buffer. */
187size_t get_buffer_len(void)
188{
189 return key_buffer_len;
190}
191
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000192/* Add the contents of the keystroke buffer input to the default
193 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000194void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000195{
196#ifndef NANO_SMALL
197 allow_pending_sigwinch(TRUE);
198 allow_pending_sigwinch(FALSE);
199#endif
200
201 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000202 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000203 return;
204
205 /* If adding input would put the default keystroke buffer beyond
206 * maximum capacity, only add enough of input to put it at maximum
207 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000208 if (key_buffer_len + input_len < key_buffer_len)
209 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000210
211 /* Add the length of input to the length of the default keystroke
212 * buffer, and reallocate the default keystroke buffer so that it
213 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000214 key_buffer_len += input_len;
215 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
216 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000217
218 /* If the default keystroke buffer wasn't empty before, move its
219 * beginning forward far enough so that we can add input to its
220 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000221 if (key_buffer_len > input_len)
222 memmove(key_buffer + input_len, key_buffer,
223 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000224
225 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000226 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000227}
228
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000229/* Put back the character stored in kbinput, putting it in byte range
230 * beforehand. If meta_key is TRUE, put back the Escape character after
231 * putting back kbinput. If func_key is TRUE, put back the function key
232 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000233void unget_kbinput(int kbinput, bool meta_key, bool func_key)
234{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000235 if (!func_key)
236 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000237
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000238 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000239
240 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000241 kbinput = NANO_CONTROL_3;
242 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000243 }
244}
245
246/* Try to read input_len characters from the default keystroke buffer.
247 * If the default keystroke buffer is empty and win isn't NULL, try to
248 * read in more characters from win and add them to the default
249 * keystroke buffer before doing anything else. If the default
250 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000251int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000252{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000253 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000254
255#ifndef NANO_SMALL
256 allow_pending_sigwinch(TRUE);
257 allow_pending_sigwinch(FALSE);
258#endif
259
260 if (key_buffer_len == 0) {
261 if (win != NULL)
262 get_buffer(win);
263
264 if (key_buffer_len == 0)
265 return NULL;
266 }
267
268 /* If input_len is greater than the length of the default keystroke
269 * buffer, only read the number of characters in the default
270 * keystroke buffer. */
271 if (input_len > key_buffer_len)
272 input_len = key_buffer_len;
273
274 /* Subtract input_len from the length of the default keystroke
275 * buffer, and allocate the keystroke buffer input so that it
276 * has enough room for input_len keystrokes. */
277 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000278 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000279
280 /* Copy input_len characters from the beginning of the default
281 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000282 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000283
284 /* If the default keystroke buffer is empty, mark it as such. */
285 if (key_buffer_len == 0) {
286 free(key_buffer);
287 key_buffer = NULL;
288 /* If the default keystroke buffer isn't empty, move its
289 * beginning forward far enough back so that the keystrokes in input
290 * are no longer at its beginning. */
291 } else {
292 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000293 sizeof(int));
294 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
295 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000296 }
297
298 return input;
299}
300
301/* Read in a single character. If it's ignored, swallow it and go on.
302 * Otherwise, try to translate it from ASCII, meta key sequences, escape
303 * sequences, and/or extended keypad values. Set meta_key to TRUE when
304 * we get a meta key sequence, and set func_key to TRUE when we get an
305 * extended keypad value. Supported extended keypad values consist of
306 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
307 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
308 * the function keypad (F1-F16), and the numeric keypad with NumLock
309 * off. Assume nodelay(win) is FALSE. */
310int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
311{
312 int kbinput;
313
314 /* Read in a character and interpret it. Continue doing this until
315 * we get a recognized value or sequence. */
316 while ((kbinput = parse_kbinput(win, meta_key, func_key
317#ifndef NANO_SMALL
318 , FALSE
319#endif
320 )) == ERR);
321
322 return kbinput;
323}
324
325/* Translate ASCII characters, extended keypad values, and escape
326 * sequences into their corresponding key values. Set meta_key to TRUE
327 * when we get a meta key sequence, and set func_key to TRUE when we get
328 * a function key. Assume nodelay(win) is FALSE. */
329int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000330#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000331 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000332#endif
333 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000334
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000335{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000336 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000337 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000338
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000339#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000340 if (reset) {
341 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000342 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000343 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000344 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000345#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000346
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000347 *meta_key = FALSE;
348 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000349
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000350 /* Read in a character. */
351 while ((kbinput = get_input(win, 1)) == NULL);
352
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000353 switch (*kbinput) {
354 case ERR:
355 break;
356 case NANO_CONTROL_3:
357 /* Increment the escape counter. */
358 escapes++;
359 switch (escapes) {
360 case 1:
361 /* One escape: wait for more input. */
362 case 2:
363 /* Two escapes: wait for more input. */
364 break;
365 default:
366 /* More than two escapes: reset the escape counter
367 * and wait for more input. */
368 escapes = 0;
369 }
370 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000371#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000372 /* Since we don't change the default SIGWINCH handler when
373 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
374 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
375 case KEY_RESIZE:
376 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000377#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000378#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000379 case KEY_SHIFT_L:
380 case KEY_SHIFT_R:
381 case KEY_CONTROL_L:
382 case KEY_CONTROL_R:
383 case KEY_ALT_L:
384 case KEY_ALT_R:
385 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000386#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000387 default:
388 switch (escapes) {
389 case 0:
390 switch (*kbinput) {
391 case NANO_CONTROL_8:
392 retval = ISSET(REBIND_DELETE) ?
393 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
394 break;
395 case KEY_DOWN:
396 retval = NANO_NEXTLINE_KEY;
397 break;
398 case KEY_UP:
399 retval = NANO_PREVLINE_KEY;
400 break;
401 case KEY_LEFT:
402 retval = NANO_BACK_KEY;
403 break;
404 case KEY_RIGHT:
405 retval = NANO_FORWARD_KEY;
406 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000407#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000408 /* HP-UX 10 and 11 don't support KEY_HOME. */
409 case KEY_HOME:
410 retval = NANO_HOME_KEY;
411 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000412#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000413 case KEY_BACKSPACE:
414 retval = NANO_BACKSPACE_KEY;
415 break;
416 case KEY_DC:
417 retval = ISSET(REBIND_DELETE) ?
418 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
419 break;
420 case KEY_IC:
421 retval = NANO_INSERTFILE_KEY;
422 break;
423 case KEY_NPAGE:
424 retval = NANO_NEXTPAGE_KEY;
425 break;
426 case KEY_PPAGE:
427 retval = NANO_PREVPAGE_KEY;
428 break;
429 case KEY_ENTER:
430 retval = NANO_ENTER_KEY;
431 break;
432 case KEY_A1: /* Home (7) on numeric keypad
433 * with NumLock off. */
434 retval = NANO_HOME_KEY;
435 break;
436 case KEY_A3: /* PageUp (9) on numeric keypad
437 * with NumLock off. */
438 retval = NANO_PREVPAGE_KEY;
439 break;
440 case KEY_B2: /* Center (5) on numeric keypad
441 * with NumLock off. */
442 break;
443 case KEY_C1: /* End (1) on numeric keypad
444 * with NumLock off. */
445 retval = NANO_END_KEY;
446 break;
447 case KEY_C3: /* PageDown (4) on numeric
448 * keypad with NumLock off. */
449 retval = NANO_NEXTPAGE_KEY;
450 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000451#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000452 /* Slang doesn't support KEY_BEG. */
453 case KEY_BEG: /* Center (5) on numeric keypad
454 * with NumLock off. */
455 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000456#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000457#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000458 /* HP-UX 10 and 11 don't support KEY_END. */
459 case KEY_END:
460 retval = NANO_END_KEY;
461 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000462#endif
463#ifdef KEY_SUSPEND
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000464 /* Slang doesn't support KEY_SUSPEND. */
465 case KEY_SUSPEND:
466 retval = NANO_SUSPEND_KEY;
467 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000468#endif
469#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000470 /* Slang doesn't support KEY_SLEFT. */
471 case KEY_SLEFT:
472 retval = NANO_BACK_KEY;
473 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000474#endif
475#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000476 /* Slang doesn't support KEY_SRIGHT. */
477 case KEY_SRIGHT:
478 retval = NANO_FORWARD_KEY;
479 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000480#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000481 default:
482 retval = *kbinput;
483 break;
484 }
485 break;
486 case 1:
487 /* One escape followed by a non-escape: escape
488 * sequence mode. Reset the escape counter. If
489 * there aren't any other keys waiting, we have a
490 * meta key sequence, so set meta_key to TRUE and
491 * save the lowercase version of the non-escape
492 * character as the result. If there are other keys
493 * waiting, we have a true escape sequence, so
494 * interpret it. */
495 escapes = 0;
496 if (get_buffer_len() == 0) {
497 *meta_key = TRUE;
498 retval = tolower(*kbinput);
499 } else {
500 int *seq;
501 size_t seq_len;
502 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000503
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000504 /* Put back the non-escape character, get the
505 * complete escape sequence, translate the
506 * sequence into its corresponding key value,
507 * and save that as the result. */
508 unget_input(kbinput, 1);
509 seq_len = get_buffer_len();
510 seq = get_input(NULL, seq_len);
511 retval = get_escape_seq_kbinput(seq, seq_len,
512 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000513
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000514 /* If the escape sequence is unrecognized and
515 * not ignored, put back all of its characters
516 * except for the initial escape. */
517 if (retval == ERR && !ignore_seq)
518 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000519
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000520 free(seq);
521 }
522 break;
523 case 2:
524 /* Two escapes followed by one or more decimal
525 * digits: byte sequence mode. If the word
526 * sequence's range is limited to 2XX (the first
527 * digit is in the '0' to '2' range and it's the
528 * first digit, or it's in the '0' to '9' range and
529 * it's not the first digit), increment the byte
530 * sequence counter and interpret the digit. If the
531 * byte sequence's range is not limited to 2XX, fall
532 * through. */
533 if (('0' <= *kbinput && *kbinput <= '6' &&
534 byte_digits == 0) || ('0' <= *kbinput &&
535 *kbinput <= '9' && byte_digits > 0)) {
536 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000537
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000538 byte_digits++;
539 byte = get_byte_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000540#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000541 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000542#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000543 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000544
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000545 if (byte != ERR) {
546 char *byte_mb = charalloc(mb_cur_max());
547 int byte_mb_len, *seq, i;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000548
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000549 /* If we've read in a complete byte
550 * sequence, reset the byte sequence counter
551 * and the escape counter, and put back the
552 * corresponding byte value. */
553 byte_digits = 0;
554 escapes = 0;
555
556 /* Put back the multibyte equivalent of the
557 * byte value. */
558 byte_mb = make_mbchar(byte, byte_mb,
559 &byte_mb_len);
560
561 seq = (int *)nmalloc(byte_mb_len *
562 sizeof(int));
563
564 for (i = 0; i < byte_mb_len; i++)
565 seq[i] = (unsigned char)byte_mb[i];
566
567 unget_input(seq, byte_mb_len);
568
569 free(seq);
570 free(byte_mb);
571 }
572 } else {
573 /* Reset the escape counter. */
574 escapes = 0;
575 if (byte_digits == 0)
576 /* Two escapes followed by a non-decimal
577 * digit or a decimal digit that would
578 * create a byte sequence greater than 2XX,
579 * and we're not in the middle of a byte
580 * sequence: control character sequence
581 * mode. Interpret the control sequence and
582 * save the corresponding control character
583 * as the result. */
584 retval = get_control_kbinput(*kbinput);
585 else {
586 /* If we're in the middle of a byte
587 * sequence, reset the byte sequence counter
588 * and save the character we got as the
589 * result. */
590 byte_digits = 0;
591 retval = *kbinput;
592 }
593 }
594 break;
595 }
596 }
597
598 /* If we have a result and it's an extended keypad value (i.e, a
599 * value outside of byte range), set func_key to TRUE. */
600 if (retval != ERR)
601 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000602
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000603#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000604 fprintf(stderr, "parse_kbinput(): kbinput = %d, meta_key = %d, func_key = %d, escapes = %d, byte_digits = %d, retval = %d\n", *kbinput, (int)*meta_key, (int)*func_key, escapes, byte_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000605#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000606
607 /* Return the result. */
608 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000609}
610
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000611/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000612 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000613 * are generated when the keypad doesn't support the needed keys. If
614 * the escape sequence is recognized but we want to ignore it, return
615 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
616 * set ignore_seq to FALSE. Assume that Escape has already been read
617 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000618int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000619 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000620{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000621 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000622
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000623 *ignore_seq = FALSE;
624
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000625 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000626 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000627 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000628 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000629 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000630 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000631 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000632 case 'P': /* Esc O 2 P == F13 on
633 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000634 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000635 break;
636 case 'Q': /* Esc O 2 Q == F14 on
637 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000638 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000639 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000640 case 'R': /* Esc O 2 R == F15 on
641 * xterm. */
642 retval = KEY_F(15);
643 break;
644 case 'S': /* Esc O 2 S == F16 on
645 * xterm. */
646 retval = KEY_F(16);
647 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000648 }
649 }
650 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000651 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
652 case 'B': /* Esc O B == Down on
653 * VT100/VT320/xterm. */
654 case 'C': /* Esc O C == Right on
655 * VT100/VT320/xterm. */
656 case 'D': /* Esc O D == Left on
657 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000658 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000659 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000660 case 'E': /* Esc O E == Center (5) on numeric keypad
661 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000662 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000663 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000664 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000665 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000666 break;
667 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000668 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000669 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000670 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000671 * NumLock off on VT100/VT220/VT320/xterm/
672 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000673 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000674 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000675 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000676 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000677 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000678 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000679 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000680 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000681 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000682 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000683 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000684 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000685 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000686 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000687 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000688 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000689 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000690 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000691 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000692 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000693 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000694 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000695 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000696 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000697 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000698 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000699 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000700 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000701 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000702 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000703 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000704 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000705 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000706 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000707 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000708 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000709 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000710 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000711 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000712 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000713 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000714 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000715 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000716 * NumLock off on VT100/VT220/VT320/xterm/
717 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000718 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000719 break;
720 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000721 * NumLock off on VT100/VT220/VT320/xterm/
722 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000723 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000724 break;
725 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000726 * NumLock off on VT100/VT220/VT320/xterm/
727 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000728 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000729 break;
730 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000731 * NumLock off on VT100/VT220/VT320/xterm/
732 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000733 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000734 break;
735 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000736 * with NumLock off on VT100/VT220/VT320/
737 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000738 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000739 break;
740 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000741 * NumLock off on VT100/VT220/VT320/xterm/
742 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000743 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000744 break;
745 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000746 * with NumLock off on VT100/VT220/VT320/
747 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000748 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000749 break;
750 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000751 * with NumLock off on VT100/VT220/VT320/
752 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000753 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000754 break;
755 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000756 * with NumLock off on VT100/VT220/VT320/
757 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000758 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000759 break;
760 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000761 * keypad with NumLock off on VT100/VT220/
762 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000763 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000764 break;
765 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000766 * with NumLock off on VT100/VT220/VT320/
767 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000768 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000769 break;
770 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000771 * with NumLock off on VT100/VT220/VT320/
772 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000773 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000774 break;
775 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000776 * with NumLock off on VT100/VT220/VT320/
777 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000778 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000779 break;
780 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000781 * with NumLock off on VT100/VT220/VT320/
782 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000783 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000784 break;
785 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000786 * with NumLock off on VT100/VT220/VT320/
787 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000788 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000789 break;
790 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000791 * with NumLock off on VT100/VT220/VT320/
792 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000793 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000794 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000795 }
796 break;
797 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000798 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000799 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000800 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000801 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000802 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000803 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000804 break;
805 }
806 break;
807 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000808 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000809 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000810 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000811 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000812 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
813 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000814 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000815 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000816 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
817 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000818 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000819 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000820 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
821 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000822 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000823 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000824 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
825 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000826 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000827 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000828 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
829 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000830 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000831 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000832 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000833 * VT220/VT320/Linux console/
834 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000835 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000836 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000837 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000838 * VT220/VT320/Linux console/
839 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000840 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000841 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000842 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000843 * VT220/VT320/Linux console/
844 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000845 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000846 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000847 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000848 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000849 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000850 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000851 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000852 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000853 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
854 * xterm. */
855 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
856 * xterm. */
857 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
858 * xterm. */
859 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
860 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000861 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000862 break;
863 }
864 }
865 break;
866 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000867 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000868 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000869 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
870 * xterm. */
871 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
872 * xterm. */
873 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
874 * xterm. */
875 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
876 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000877 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000878 break;
879 }
880 }
881 break;
882 }
883 }
884 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000885 default: /* Esc [ 1 ~ == Home on
886 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000887 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000888 break;
889 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000890 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000891 break;
892 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000893 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000894 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000895 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000896 * VT220/VT320/Linux console/
897 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000898 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000899 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000900 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000901 * VT220/VT320/Linux console/
902 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000903 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000904 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000905 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000906 * VT220/VT320/Linux console/
907 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000908 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000909 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000910 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000911 * VT220/VT320/Linux console/
912 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000913 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000914 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000915 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000916 * VT220/VT320/Linux console/
917 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000918 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000919 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000920 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000921 * VT220/VT320/Linux console/
922 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000923 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000924 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000925 case '8': /* Esc [ 2 8 ~ == F15 on
926 * VT220/VT320/Linux console/
927 * rxvt/Eterm. */
928 retval = KEY_F(15);
929 break;
930 case '9': /* Esc [ 2 9 ~ == F16 on
931 * VT220/VT320/Linux console/
932 * rxvt/Eterm. */
933 retval = KEY_F(16);
934 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000935 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000936 * VT220/VT320/Linux console/
937 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000938 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000939 break;
940 }
941 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000942 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000943 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
944 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000945 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000946 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000947 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000948 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000949 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000950 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000951 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
952 * Linux console/xterm; Esc [ 5 ^ ==
953 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000954 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000955 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000956 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
957 * Linux console/xterm; Esc [ 6 ^ ==
958 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000959 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000960 break;
961 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000962 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000963 break;
964 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000965 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000966 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000967 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000968 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000969 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000970 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000971 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000972 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000973 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000974 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000975 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000976 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000977 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000978 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000979 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000980 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000981 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000982 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000983 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000984 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000985 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000986 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000987 case 'E': /* Esc [ E == Center (5) on numeric keypad
988 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000989 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000990 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000991 case 'F': /* Esc [ F == End on FreeBSD
992 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000993 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000994 break;
995 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000996 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000997 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000998 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000999 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001000 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001001 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001002 break;
1003 case 'I': /* Esc [ I == PageUp on FreeBSD
1004 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001005 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001006 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001007 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001008 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001009 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001010 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001011 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001012 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001013 break;
1014 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001015 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001016 break;
1017 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001018 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001019 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001020 case 'P': /* Esc [ O P == F1 on
1021 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001022 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001023 break;
1024 case 'Q': /* Esc [ O Q == F2 on
1025 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001026 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001027 break;
1028 case 'R': /* Esc [ O R == F3 on
1029 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001030 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001031 break;
1032 case 'S': /* Esc [ O S == F4 on
1033 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001034 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001035 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001036 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001037 } else {
1038 /* Esc [ O == F3 on FreeBSD console. */
1039 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001040 }
1041 break;
1042 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001043 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001044 break;
1045 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001046 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001047 break;
1048 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001049 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001050 break;
1051 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001052 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001053 break;
1054 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001055 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001056 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001057 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001058 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001059 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001060 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001062 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001063 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001064 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001065 break;
1066 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001067 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001068 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001069 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001070 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001071 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001072 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001073 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001074 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001075 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001076 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001077 case 'c': /* Esc [ c == Shift-Right on rxvt/
1078 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001079 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001080 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001081 break;
1082 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001083 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001084 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001085 case 'A': /* Esc [ [ A == F1 on Linux
1086 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001087 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001088 break;
1089 case 'B': /* Esc [ [ B == F2 on Linux
1090 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001091 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001092 break;
1093 case 'C': /* Esc [ [ C == F3 on Linux
1094 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001095 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001096 break;
1097 case 'D': /* Esc [ [ D == F4 on Linux
1098 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001099 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001100 break;
1101 case 'E': /* Esc [ [ E == F5 on Linux
1102 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001103 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001104 break;
1105 }
1106 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001107 break;
1108 }
1109 break;
1110 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001111 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001112
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001113#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001114 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001115#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001116
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001117 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001118}
1119
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001120/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001121 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001122 * to many escape sequences. */
1123int get_escape_seq_abcd(int kbinput)
1124{
1125 switch (tolower(kbinput)) {
1126 case 'a':
1127 return NANO_PREVLINE_KEY;
1128 case 'b':
1129 return NANO_NEXTLINE_KEY;
1130 case 'c':
1131 return NANO_FORWARD_KEY;
1132 case 'd':
1133 return NANO_BACK_KEY;
1134 default:
1135 return ERR;
1136 }
1137}
1138
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001139/* Translate a byte sequence: turn a three-digit decimal number from
1140 * 000 to 255 into its corresponding byte value. */
1141int get_byte_kbinput(int kbinput
1142#ifndef NANO_SMALL
1143 , bool reset
1144#endif
1145 )
1146{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001147 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001148 int retval = ERR;
1149
1150#ifndef NANO_SMALL
1151 if (reset) {
1152 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001153 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001154 return ERR;
1155 }
1156#endif
1157
1158 /* Increment the byte digit counter. */
1159 byte_digits++;
1160
1161 switch (byte_digits) {
1162 case 1:
1163 /* One digit: reset the byte sequence holder and add the
1164 * digit we got to the 100's position of the byte sequence
1165 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001166 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001167 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001168 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001169 else
1170 /* If the character we got isn't a decimal digit, or if
1171 * it is and it would put the byte sequence out of byte
1172 * range, save it as the result. */
1173 retval = kbinput;
1174 break;
1175 case 2:
1176 /* Two digits: add the digit we got to the 10's position of
1177 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001178 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1179 '6' <= kbinput && kbinput <= '9'))
1180 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001181 else
1182 /* If the character we got isn't a decimal digit, or if
1183 * it is and it would put the byte sequence out of byte
1184 * range, save it as the result. */
1185 retval = kbinput;
1186 break;
1187 case 3:
1188 /* Three digits: add the digit we got to the 1's position of
1189 * the byte sequence holder, and save the corresponding word
1190 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001191 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1192 '6' <= kbinput && kbinput <= '9')) {
1193 byte += (kbinput - '0');
1194 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001195 } else
1196 /* If the character we got isn't a decimal digit, or if
1197 * it is and it would put the word sequence out of word
1198 * range, save it as the result. */
1199 retval = kbinput;
1200 break;
1201 default:
1202 /* More than three digits: save the character we got as the
1203 * result. */
1204 retval = kbinput;
1205 break;
1206 }
1207
1208 /* If we have a result, reset the byte digit counter and the byte
1209 * sequence holder. */
1210 if (retval != ERR) {
1211 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001212 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001213 }
1214
1215#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001216 fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte = %d, retval = %d\n", kbinput, byte_digits, byte, retval);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001217#endif
1218
1219 return retval;
1220}
1221
1222/* Translate a word sequence: turn a four-digit hexadecimal number from
1223 * 0000 to ffff (case-insensitive) into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001224int get_word_kbinput(int kbinput
1225#ifndef NANO_SMALL
1226 , bool reset
1227#endif
1228 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001229{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001230 static int word_digits = 0, word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001231 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001232
1233#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001234 if (reset) {
1235 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001236 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001237 return ERR;
1238 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001239#endif
1240
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001241 /* Increment the word digit counter. */
1242 word_digits++;
1243
1244 switch (word_digits) {
1245 case 1:
1246 /* One digit: reset the word sequence holder and add the
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001247 * digit we got to the 4096's position of the word sequence
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001248 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001249 word = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001250 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001251 word += (kbinput - '0') * 4096;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001252 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001253 word += (tolower(kbinput) + 10 - 'a') * 4096;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001254 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001255 /* If the character we got isn't a hexadecimal digit, or
1256 * if it is and it would put the word sequence out of
1257 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001258 retval = kbinput;
1259 break;
1260 case 2:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001261 /* Two digits: add the digit we got to the 256's position of
1262 * the word sequence holder. */
1263 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001264 word += (kbinput - '0') * 256;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001265 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001266 word += (tolower(kbinput) + 10 - 'a') * 256;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001267 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001268 /* If the character we got isn't a hexadecimal digit, or
1269 * if it is and it would put the word sequence out of
1270 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001271 retval = kbinput;
1272 break;
1273 case 3:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001274 /* Three digits: add the digit we got to the 16's position
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001275 * of the word sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001276 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001277 word += (kbinput - '0') * 16;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001278 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001279 word += (tolower(kbinput) + 10 - 'a') * 16;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001280 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001281 /* If the character we got isn't a hexadecimal digit, or
1282 * if it is and it would put the word sequence out of
1283 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001284 retval = kbinput;
1285 break;
1286 case 4:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001287 /* Four digits: add the digit we got to the 1's position of
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001288 * the word sequence holder, and save the corresponding word
1289 * value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001290 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001291 word += (kbinput - '0');
1292 retval = word;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001293 } else if ('a' <= tolower(kbinput) &&
1294 tolower(kbinput) <= 'f') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001295 word += (tolower(kbinput) + 10 - 'a');
1296 retval = word;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001297 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001298 /* If the character we got isn't a hexadecimal digit, or
1299 * if it is and it would put the word sequence out of
1300 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001301 retval = kbinput;
1302 break;
1303 default:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001304 /* More than four digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001305 * result. */
1306 retval = kbinput;
1307 break;
1308 }
1309
1310 /* If we have a result, reset the word digit counter and the word
1311 * sequence holder. */
1312 if (retval != ERR) {
1313 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001314 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001315 }
1316
1317#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001318 fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word = %d, retval = %d\n", kbinput, word_digits, word, retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001319#endif
1320
1321 return retval;
1322}
1323
1324/* Translate a control character sequence: turn an ASCII non-control
1325 * character into its corresponding control character. */
1326int get_control_kbinput(int kbinput)
1327{
1328 int retval;
1329
1330 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1331 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1332 kbinput == '`')
1333 retval = NANO_CONTROL_SPACE;
1334 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1335 else if ('3' <= kbinput && kbinput <= '7')
1336 retval = kbinput - 24;
1337 /* Ctrl-8 (Ctrl-?) */
1338 else if (kbinput == '8' || kbinput == '?')
1339 retval = NANO_CONTROL_8;
1340 /* Ctrl-A to Ctrl-_ */
1341 else if ('A' <= kbinput && kbinput <= '_')
1342 retval = kbinput - 64;
1343 /* Ctrl-a to Ctrl-~ */
1344 else if ('a' <= kbinput && kbinput <= '~')
1345 retval = kbinput - 96;
1346 else
1347 retval = kbinput;
1348
1349#ifdef DEBUG
1350 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1351#endif
1352
1353 return retval;
1354}
1355
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001356/* Put the output-formatted characters in output back into the default
1357 * keystroke buffer, so that they can be parsed and displayed as output
1358 * again. */
1359void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001360{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001361 int *input;
1362 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001363
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001364 if (output_len == 0)
1365 return;
1366
1367 input = (int *)nmalloc(output_len * sizeof(int));
1368 for (i = 0; i < output_len; i++)
1369 input[i] = (int)output[i];
1370 unget_input(input, output_len);
1371 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001372}
1373
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001374/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001375 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1376int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1377{
1378 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001379
1380 /* Turn off flow control characters if necessary so that we can type
1381 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001382 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001383 if (ISSET(PRESERVE))
1384 disable_flow_control();
1385 keypad(win, FALSE);
1386
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001387 /* Read in a stream of characters and interpret it if possible. */
1388 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001389
1390 /* Turn flow control characters back on if necessary and turn the
1391 * keypad back on now that we're done. */
1392 if (ISSET(PRESERVE))
1393 enable_flow_control();
1394 keypad(win, TRUE);
1395
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001396 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001397}
1398
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001399/* Read in a stream of all available characters, and return the length
1400 * of the string in kbinput_len. Translate the first few characters of
1401 * the input into the corresponding word value if possible. After that,
1402 * leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001403int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001404{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001405 int *kbinput, word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001406
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001407 /* Read in the first keystroke. */
1408 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001409
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001410 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001411 word = get_word_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001412#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001413 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001414#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001415 );
1416
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001417 /* If the first keystroke isn't a hexadecimal digit, put back the
1418 * first keystroke. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001419 if (word != ERR)
1420 unget_input(kbinput, 1);
1421 /* Otherwise, read in keystrokes until we have a complete word
1422 * sequence, and put back the corresponding word value. */
1423 else {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001424 char *word_mb = charalloc(mb_cur_max());
1425 int word_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001426
1427 while (word == ERR) {
1428 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001429
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001430 word = get_word_kbinput(*kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001431#ifndef NANO_SMALL
1432 , FALSE
1433#endif
1434 );
1435 }
1436
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001437 /* Put back the multibyte equivalent of the word value. */
1438 word_mb = make_mbchar(word, word_mb, &word_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001439
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001440 seq = (int *)nmalloc(word_mb_len * sizeof(int));
1441
1442 for (i = 0; i < word_mb_len; i++)
1443 seq[i] = (unsigned char)word_mb[i];
1444
1445 unget_input(seq, word_mb_len);
1446
1447 free(seq);
1448 free(word_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001449 }
1450
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001451 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001452 * result. */
1453 *kbinput_len = get_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001454 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001455
1456 return retval;
1457}
1458
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001459#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001460/* Check for a mouse event, and if one's taken place, save the
1461 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001462 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1463 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001464 * place on it, figure out which shortcut was clicked and put back the
1465 * equivalent keystroke(s). Return FALSE if no keystrokes were
1466 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001467 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001468bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001469{
1470 MEVENT mevent;
1471
1472 *mouse_x = -1;
1473 *mouse_y = -1;
1474
1475 /* First, get the actual mouse event. */
1476 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001477 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001478
1479 /* Save the screen coordinates where the mouse event took place. */
1480 *mouse_x = mevent.x;
1481 *mouse_y = mevent.y;
1482
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001483 /* If we're allowing shortcuts, the current shortcut list is being
1484 * displayed on the last two lines of the screen, and the mouse
1485 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001486 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001487 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1488 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001489 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001490 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001491 /* The number of shortcuts in the current shortcut list. */
1492 const shortcut *s = currshortcut;
1493 /* The actual shortcut we clicked on, starting at the first
1494 * one in the current shortcut list. */
1495
1496 /* Get the shortcut lists' length. */
1497 if (currshortcut == main_list)
1498 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001499 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001500 currslen = length_of_list(currshortcut);
1501
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001502 /* We don't show any more shortcuts than the main list
1503 * does. */
1504 if (currslen > MAIN_VISIBLE)
1505 currslen = MAIN_VISIBLE;
1506 }
1507
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001508 /* Calculate the width of each shortcut in the list (it's the
1509 * same for all of them). */
1510 if (currslen < 2)
1511 i = COLS / 6;
1512 else
1513 i = COLS / ((currslen / 2) + (currslen % 2));
1514
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001515 /* Calculate the y-coordinate relative to the beginning of
1516 * bottomwin. */
1517 j = *mouse_y - ((2 - no_more_space()) + 1) - editwinrows;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001518
1519 /* If we're on the statusbar, beyond the end of the shortcut
1520 * list, or beyond the end of a shortcut on the right side of
1521 * the screen, don't do anything. */
1522 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001523 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001524 j = (*mouse_x / i) * 2 + j;
1525 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001526 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001527
1528 /* Go through the shortcut list to determine which shortcut was
1529 * clicked. */
1530 for (; j > 0; j--)
1531 s = s->next;
1532
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001533 /* And put back the equivalent key. Assume that each shortcut
1534 * has, at the very least, an equivalent control key, an
1535 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001536 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001537 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001538 return TRUE;
1539 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001540 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001541 return TRUE;
1542 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001543 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001544 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001545}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001546#endif /* !DISABLE_MOUSE */
1547
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001548const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001549 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001550{
1551 const shortcut *s = s_list;
1552 size_t slen = length_of_list(s_list);
1553
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001554#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001555 fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %d, func_key = %d\n", *kbinput, (int)*meta_key, (int)*func_key);
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001556#endif
1557
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001558 /* Check for shortcuts. */
1559 for (; slen > 0; slen--) {
1560 /* We've found a shortcut if:
1561 *
1562 * 1. The key exists.
1563 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001564 * 3. meta_key is TRUE and the key is the primary or
1565 * miscellaneous meta sequence in the shortcut list.
1566 * 4. func_key is TRUE and the key is a function key in the
1567 * shortcut list. */
1568
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001569 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1570 (*meta_key == TRUE && (*kbinput == s->metaval ||
1571 *kbinput == s->miscval)) || (*func_key == TRUE &&
1572 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001573 break;
1574 }
1575
1576 s = s->next;
1577 }
1578
1579 /* Translate the shortcut to either its control key or its meta key
1580 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001581 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001582 if (slen > 0) {
1583 if (s->ctrlval != NANO_NO_KEY) {
1584 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001585 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001586 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001587 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001588 } else if (s->metaval != NANO_NO_KEY) {
1589 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001590 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001591 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001592 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001593 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001594 }
1595
1596 return NULL;
1597}
1598
1599#ifndef NANO_SMALL
1600const toggle *get_toggle(int kbinput, bool meta_key)
1601{
1602 const toggle *t = toggles;
1603
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001604#ifdef DEBUG
1605 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1606#endif
1607
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001608 /* Check for toggles. */
1609 for (; t != NULL; t = t->next) {
1610 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001611 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001612 if (meta_key && kbinput == t->val)
1613 break;
1614 }
1615
1616 return t;
1617}
1618#endif /* !NANO_SMALL */
1619
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001620int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001621 bool *ran_func, bool *finished, bool allow_funcs)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001622{
1623 int input;
1624 /* The character we read in. */
1625 static int *kbinput = NULL;
1626 /* The input buffer. */
1627 static size_t kbinput_len = 0;
1628 /* The length of the input buffer. */
1629 const shortcut *s;
1630 bool have_shortcut;
1631
1632 *s_or_t = FALSE;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001633 *ran_func = FALSE;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001634 *finished = FALSE;
1635
1636 /* Read in a character. */
1637 input = get_kbinput(bottomwin, meta_key, func_key);
1638
1639#ifndef DISABLE_MOUSE
1640 /* If we got a mouse click and it was on a shortcut, read in the
1641 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001642 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001643 if (do_mouse())
1644 input = get_kbinput(bottomwin, meta_key, func_key);
1645 else
1646 input = ERR;
1647 }
1648#endif
1649
1650 /* Check for a shortcut in the current list. */
1651 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1652
1653 /* If we got a shortcut from the current list, or a "universal"
1654 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1655 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1656 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1657 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1658 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001659 input == NANO_CUT_KEY ||
1660#ifndef NANO_SMALL
1661 input == NANO_NEXTWORD_KEY ||
1662#endif
1663 (*meta_key == TRUE && (
1664#ifndef NANO_SMALL
1665 input == NANO_PREVWORD_KEY ||
1666#endif
1667 input == NANO_VERBATIM_KEY)));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001668
1669 /* Set s_or_t to TRUE if we got a shortcut. */
1670 *s_or_t = have_shortcut;
1671
1672 if (allow_funcs) {
1673 if (input != ERR && *s_or_t == FALSE && !is_cntrl_char(input)) {
1674 /* If we're using restricted mode, the filename isn't blank,
1675 * and we're at the "Write File" prompt, disable text
1676 * input. */
1677 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1678 currshortcut != writefile_list) {
1679 kbinput_len++;
1680 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1681 sizeof(int));
1682 kbinput[kbinput_len - 1] = input;
1683 }
1684 }
1685
1686 /* If we got a shortcut, or if there aren't any other characters
1687 * waiting after the one we read in, we need to display all the
1688 * characters in the input buffer if it isn't empty. */
1689 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1690 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001691
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001692 /* Display all the characters in the input buffer at
1693 * once. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001694 char *output = charalloc(kbinput_len + 1);
1695 size_t i;
1696 bool got_enter;
1697 /* Whether we got the Enter key. */
1698
1699 for (i = 0; i < kbinput_len; i++)
1700 output[i] = (char)kbinput[i];
1701 output[i] = '\0';
1702
1703 do_statusbar_output(output, kbinput_len, &got_enter);
1704
1705 free(output);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001706
1707 /* Empty the input buffer. */
1708 kbinput_len = 0;
1709 free(kbinput);
1710 kbinput = NULL;
1711 }
1712 }
1713
1714 if (have_shortcut) {
1715 switch (input) {
1716 /* Handle the "universal" statusbar prompt shortcuts. */
1717 case NANO_REFRESH_KEY:
1718 total_refresh();
1719 break;
1720 case NANO_HOME_KEY:
1721 do_statusbar_home();
1722 break;
1723 case NANO_END_KEY:
1724 do_statusbar_end();
1725 break;
1726 case NANO_FORWARD_KEY:
1727 do_statusbar_right();
1728 break;
1729 case NANO_BACK_KEY:
1730 do_statusbar_left();
1731 break;
1732 case NANO_BACKSPACE_KEY:
1733 /* If we're using restricted mode, the filename
1734 * isn't blank, and we're at the "Write File"
1735 * prompt, disable Backspace. */
1736 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1737 currshortcut != writefile_list)
1738 do_statusbar_backspace();
1739 break;
1740 case NANO_DELETE_KEY:
1741 /* If we're using restricted mode, the filename
1742 * isn't blank, and we're at the "Write File"
1743 * prompt, disable Delete. */
1744 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1745 currshortcut != writefile_list)
1746 do_statusbar_delete();
1747 break;
1748 case NANO_CUT_KEY:
1749 /* If we're using restricted mode, the filename
1750 * isn't blank, and we're at the "Write File"
1751 * prompt, disable Cut. */
1752 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1753 currshortcut != writefile_list)
1754 do_statusbar_cut_text();
1755 break;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001756#ifndef NANO_SMALL
1757 case NANO_NEXTWORD_KEY:
1758 do_statusbar_next_word();
1759 break;
1760 case NANO_PREVWORD_KEY:
1761 if (*meta_key == TRUE)
1762 do_statusbar_prev_word();
1763 break;
1764#endif
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001765 case NANO_VERBATIM_KEY:
1766 if (*meta_key == TRUE) {
1767 /* If we're using restricted mode, the filename
1768 * isn't blank, and we're at the "Write File"
1769 * prompt, disable verbatim input. */
1770 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001771 currshortcut != writefile_list) {
1772 bool got_enter;
1773 /* Whether we got the Enter key. */
1774
1775 do_statusbar_verbatim_input(&got_enter);
1776
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001777 /* If we got the Enter key, set input to the
1778 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001779 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001780 if (got_enter) {
1781 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001782 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001783 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001784 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001785 break;
1786 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001787 /* Handle the normal statusbar prompt shortcuts, setting
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001788 * ran_func to TRUE if we try to run their associated
1789 * functions and setting finished to TRUE to indicate
1790 * that we're done after trying to run their associated
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001791 * functions. */
1792 default:
1793 if (s->func != NULL) {
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001794 *ran_func = TRUE;
1795 if (!ISSET(VIEW_MODE) || s->viewok)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001796 s->func();
1797 }
1798 *finished = TRUE;
1799 }
1800 }
1801 }
1802
1803 return input;
1804}
1805
1806#ifndef DISABLE_MOUSE
1807bool do_statusbar_mouse(void)
1808{
1809 /* FIXME: If we clicked on a location in the statusbar, the cursor
1810 * should move to the location we clicked on. This functionality
1811 * should be in this function. */
1812 int mouse_x, mouse_y;
1813 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1814}
1815#endif
1816
1817void do_statusbar_home(void)
1818{
1819#ifndef NANO_SMALL
1820 if (ISSET(SMART_HOME)) {
1821 size_t statusbar_x_save = statusbar_x;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001822
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001823 statusbar_x = indent_length(answer);
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001824
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001825 if (statusbar_x == statusbar_x_save ||
1826 statusbar_x == statusbar_xend)
1827 statusbar_x = 0;
1828 } else
1829#endif
1830 statusbar_x = 0;
1831}
1832
1833void do_statusbar_end(void)
1834{
1835 statusbar_x = statusbar_xend;
1836}
1837
1838void do_statusbar_right(void)
1839{
1840 if (statusbar_x < statusbar_xend)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001841 statusbar_x = move_mbright(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001842}
1843
1844void do_statusbar_left(void)
1845{
1846 if (statusbar_x > 0)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001847 statusbar_x = move_mbleft(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001848}
1849
1850void do_statusbar_backspace(void)
1851{
1852 if (statusbar_x > 0) {
1853 do_statusbar_left();
1854 do_statusbar_delete();
1855 }
1856}
1857
1858void do_statusbar_delete(void)
1859{
1860 if (statusbar_x < statusbar_xend) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001861 int char_buf_len = parse_mbchar(answer + statusbar_x, NULL,
1862 NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001863
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001864 charmove(answer + statusbar_x, answer + statusbar_x +
1865 char_buf_len, statusbar_xend - statusbar_x -
1866 char_buf_len + 1);
1867 statusbar_xend -= char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001868 }
1869}
1870
1871void do_statusbar_cut_text(void)
1872{
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001873 if (ISSET(CUT_TO_END)) {
1874 null_at(&answer, statusbar_x);
1875 statusbar_xend = statusbar_x;
1876 } else {
1877 null_at(&answer, 0);
1878 statusbar_x = 0;
1879 statusbar_xend = 0;
1880 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001881}
1882
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001883#ifndef NANO_SMALL
1884void do_statusbar_next_word(void)
1885{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001886 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001887 int char_mb_len;
1888
1889 assert(answer != NULL);
1890
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001891 char_mb = charalloc(mb_cur_max());
1892
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001893 /* Move forward until we find the character after the last letter of
1894 * the current word. */
1895 while (statusbar_x < statusbar_xend) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001896 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1897 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001898
1899 /* If we've found it, stop moving forward through the current
1900 * line. */
1901 if (!is_alnum_mbchar(char_mb))
1902 break;
1903
1904 statusbar_x += char_mb_len;
1905 }
1906
1907 /* Move forward until we find the first letter of the next word. */
1908 if (statusbar_x < statusbar_xend)
1909 current_x += char_mb_len;
1910
1911 while (statusbar_x < statusbar_xend) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001912 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1913 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001914
1915 /* If we've found it, stop moving forward through the current
1916 * line. */
1917 if (is_alnum_mbchar(char_mb))
1918 break;
1919
1920 statusbar_x += char_mb_len;
1921 }
1922
1923 free(char_mb);
1924}
1925
1926void do_statusbar_prev_word(void)
1927{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001928 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001929 int char_mb_len;
1930 bool begin_line = FALSE;
1931
1932 assert(answer != NULL);
1933
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001934 char_mb = charalloc(mb_cur_max());
1935
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001936 /* Move backward until we find the character before the first letter
1937 * of the current word. */
1938 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001939 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1940 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001941
1942 /* If we've found it, stop moving backward through the current
1943 * line. */
1944 if (!is_alnum_mbchar(char_mb))
1945 break;
1946
1947 if (statusbar_x == 0)
1948 begin_line = TRUE;
1949 else
1950 statusbar_x = move_mbleft(answer, statusbar_x);
1951 }
1952
1953 /* Move backward until we find the last letter of the previous
1954 * word. */
1955 if (statusbar_x == 0)
1956 begin_line = TRUE;
1957 else
1958 statusbar_x = move_mbleft(answer, statusbar_x);
1959
1960 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001961 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1962 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001963
1964 /* If we've found it, stop moving backward through the current
1965 * line. */
1966 if (is_alnum_mbchar(char_mb))
1967 break;
1968
1969 if (statusbar_x == 0)
1970 begin_line = TRUE;
1971 else
1972 statusbar_x = move_mbleft(answer, statusbar_x);
1973 }
1974
1975 /* If we've found it, move backward until we find the character
1976 * before the first letter of the previous word. */
1977 if (!begin_line) {
1978 if (statusbar_x == 0)
1979 begin_line = TRUE;
1980 else
1981 statusbar_x = move_mbleft(answer, statusbar_x);
1982
1983 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001984 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
1985 NULL, NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001986
1987 /* If we've found it, stop moving backward through the
1988 * current line. */
1989 if (!is_alnum_mbchar(char_mb))
1990 break;
1991
1992 if (statusbar_x == 0)
1993 begin_line = TRUE;
1994 else
1995 statusbar_x = move_mbleft(answer, statusbar_x);
1996 }
1997
1998 /* If we've found it, move forward to the first letter of the
1999 * previous word. */
2000 if (!begin_line)
2001 statusbar_x += char_mb_len;
2002 }
2003
2004 free(char_mb);
2005}
2006#endif
2007
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002008void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002009{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002010 int *kbinput;
2011 size_t kbinput_len, i;
2012 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002013
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002014 *got_enter = FALSE;
2015
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002016 /* Read in all the verbatim characters. */
2017 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
2018
2019 /* Display all the verbatim characters at once. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002020 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002021
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002022 for (i = 0; i < kbinput_len; i++)
2023 output[i] = (char)kbinput[i];
2024 output[i] = '\0';
2025
2026 do_statusbar_output(output, kbinput_len, got_enter);
2027
2028 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002029}
2030
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002031void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002032 *got_enter)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002033{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002034 size_t i = 0;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002035
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002036 char *char_buf = charalloc(mb_cur_max());
2037 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002038
2039 assert(answer != NULL);
2040
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002041 *got_enter = FALSE;
2042
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002043 while (i < output_len) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002044 /* Null to newline, if needed. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002045 if (output[i] == '\0')
2046 output[i] = '\n';
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002047 /* Newline to Enter, if needed. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002048 else if (output[i] == '\n') {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002049 /* Set got_enter to TRUE to indicate that we got the Enter
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002050 * key, put back the rest of the characters in output so
2051 * that they can be parsed and output again, and get out. */
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002052 *got_enter = TRUE;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002053 unparse_kbinput(output + i, output_len - i);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002054 return;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002055 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002056
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002057 /* Interpret the next multibyte character. If it's an invalid
2058 * multibyte character, interpret it as though it's a byte
2059 * character. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002060 char_buf_len = parse_mbchar(output + i, char_buf, NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002061
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002062 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002063
2064 /* More dangerousness fun =) */
David Lawrence Ramsey49ff08b2005-01-14 04:13:45 +00002065 answer = charealloc(answer, statusbar_xend +
2066 (char_buf_len * 2));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002067
2068 assert(statusbar_x <= statusbar_xend);
2069
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002070 charmove(&answer[statusbar_x + char_buf_len],
2071 &answer[statusbar_x], statusbar_xend - statusbar_x +
2072 char_buf_len);
2073 charcpy(&answer[statusbar_x], char_buf, char_buf_len);
2074 statusbar_xend += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002075
2076 do_statusbar_right();
2077 }
2078
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002079 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002080}
2081
Chris Allegretta6df90f52002-07-19 01:08:59 +00002082/* Return the placewewant associated with current_x. That is, xplustabs
2083 * is the zero-based column position of the cursor. Value is no smaller
2084 * than current_x. */
2085size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002086{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002087 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002088}
2089
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002090/* actual_x() gives the index in str of the character displayed at
2091 * column xplus. That is, actual_x() is the largest value such that
2092 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2093size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002094{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002095 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002096 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002097 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002098 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002099
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002100 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002101
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002102 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002103 int str_len = parse_mbchar(str, NULL, NULL, &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002104
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002105 if (length > xplus)
2106 break;
2107
2108 i += str_len;
2109 str += str_len;
2110 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002111
Chris Allegretta6df90f52002-07-19 01:08:59 +00002112 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002113}
2114
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002115/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002116 * columns wide are the first size characters of str? */
2117size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002118{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002119 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002120 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002121
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002122 if (size == 0)
2123 return 0;
2124
2125 assert(str != NULL);
2126
2127 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002128 int str_len = parse_mbchar(str, NULL, NULL, &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002129
2130 str += str_len;
2131
2132 if (size <= str_len)
2133 break;
2134
2135 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002136 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002137
Chris Allegretta6df90f52002-07-19 01:08:59 +00002138 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002139}
2140
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002141/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002142size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002143{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002144 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002145}
2146
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002147void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002148{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002149 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002150}
2151
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002152void blank_topbar(void)
2153{
2154 if (!ISSET(MORE_SPACE))
2155 mvwaddstr(topwin, 1, 0, hblank);
2156}
2157
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002158void blank_edit(void)
2159{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002160 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002161 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002162 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002163}
2164
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002165void blank_statusbar(void)
2166{
2167 mvwaddstr(bottomwin, 0, 0, hblank);
2168}
2169
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002170void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002171{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002172 if (statusblank > 1)
2173 statusblank--;
2174 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
2175 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002176 blank_statusbar();
2177 wnoutrefresh(bottomwin);
2178 reset_cursor();
2179 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002180 }
2181}
2182
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002183void blank_bottombars(void)
2184{
2185 if (!ISSET(NO_HELP)) {
2186 mvwaddstr(bottomwin, 1, 0, hblank);
2187 mvwaddstr(bottomwin, 2, 0, hblank);
2188 }
2189}
2190
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002191/* Convert buf into a string that can be displayed on screen. The
2192 * caller wants to display buf starting with column start_col, and
2193 * extending for at most len columns. start_col is zero-based. len is
2194 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002195 * string is dynamically allocated, and should be freed. If dollars is
2196 * TRUE, the caller might put "$" at the beginning or end of the line if
2197 * it's too long. */
2198char *display_string(const char *buf, size_t start_col, size_t len, bool
2199 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002200{
2201 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002202 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002203 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002204 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002205 size_t alloc_len;
2206 /* The length of memory allocated for converted. */
2207 char *converted;
2208 /* The string we return. */
2209 size_t index;
2210 /* Current position in converted. */
2211
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002212 char *buf_mb = charalloc(mb_cur_max());
2213 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002214 bool bad_char;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002215
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002216 /* If dollars is TRUE, make room for the "$" at the end of the
2217 * line. */
2218 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2219 len--;
2220
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002221 if (len == 0)
2222 return mallocstrcpy(NULL, "");
2223
2224 start_index = actual_x(buf, start_col);
2225 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002226
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002227 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002228
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002229 /* Allocate enough space for the entire line. It should contain
2230 * (len + 2) multibyte characters at most. */
2231 alloc_len = mb_cur_max() * (len + 2);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002232
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002233 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002234 index = 0;
2235
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002236 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002237 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002238 /* We don't display all of buf[start_index] since it starts to
2239 * the left of the screen. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002240 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL,
2241 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002242
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002243 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002244 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002245 char *ctrl_buf_mb = charalloc(mb_cur_max());
2246 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002247
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002248 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2249 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002250
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002251 for (i = 0; i < ctrl_buf_mb_len; i++)
2252 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002253
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002254 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002255
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002256 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002257
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002258 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002259 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002260 }
2261#ifdef NANO_WIDE
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002262 else if (mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002263 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002264 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002265
2266 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002267 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002268#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002269 }
2270
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002271 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseybc149412005-02-11 20:23:00 +00002272 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, &bad_char,
2273 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002274
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002275 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002276 converted[index++] =
2277#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2278 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
2279#endif
2280 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002281 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002282 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002283 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002284 start_col++;
2285 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002286 /* If buf contains a control character, interpret it. If it
2287 * contains an invalid multibyte control character, interpret
2288 * that character as though it's a normal control character. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002289 } else if (is_cntrl_mbchar(buf_mb)) {
2290 char *ctrl_buf_mb = charalloc(mb_cur_max());
2291 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002292
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002293 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002294 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002295
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002296 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2297 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002298
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002299 for (i = 0; i < ctrl_buf_mb_len; i++)
2300 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002301
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002302 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002303
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002304 free(ctrl_buf_mb);
2305 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002306 converted[index++] =
2307#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2308 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
2309#endif
2310 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002311 start_col++;
2312 } else {
2313 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002314
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002315#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002316 /* If buf contains an invalid multibyte non-control
2317 * character, interpret that character as though it's a
2318 * normal non-control character. */
2319 if (!ISSET(NO_UTF8) && bad_char) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002320 char *bad_buf_mb = charalloc(mb_cur_max());
2321 int bad_buf_mb_len;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002322
David Lawrence Ramsey4c6956b2005-01-12 04:32:43 +00002323 bad_buf_mb = make_mbchar((unsigned char)*buf_mb,
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002324 bad_buf_mb, &bad_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002325
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002326 for (i = 0; i < bad_buf_mb_len; i++)
2327 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002328
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002329 start_col += mbwidth(bad_buf_mb);
2330
2331 free(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002332 } else {
2333#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002334 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002335 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002336
2337 start_col += mbwidth(buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002338#ifdef NANO_WIDE
2339 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002340#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002341 }
2342
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002343 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002344 }
2345
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002346 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002347 converted[index] = '\0';
2348
2349 /* Make sure converted takes up no more than len columns. */
2350 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002351 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002352
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002353 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002354}
2355
Chris Allegretta7662c862003-01-13 01:35:15 +00002356/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002357 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002358 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002359 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002360 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002361void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002362{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002363 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002364 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002365
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002366 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002367
Chris Allegrettab3655b42001-10-22 03:15:31 +00002368 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002369 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002370
Chris Allegretta6df90f52002-07-19 01:08:59 +00002371 mvwaddstr(bottomwin, 0, 0, buf);
2372 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002373
2374 if (COLS > 1)
2375 waddch(bottomwin, x_real < wid ? ' ' : '$');
2376 if (COLS > 2) {
2377 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002378 char *expanded = display_string(inputbuf, page_start, wid,
2379 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002380
2381 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002382 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002383
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002384 waddstr(bottomwin, expanded);
2385 free(expanded);
2386 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2387 } else
2388 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002389 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002390}
2391
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002392/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002393 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002394int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002395#ifndef NANO_SMALL
2396 historyheadtype *history_list,
2397#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002398 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002399#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002400 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002401#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002402 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002403{
2404 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002405 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002406 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002407 /* used by input_tab() */
Chris Allegretta598106e2002-01-19 01:59:37 +00002408
Chris Allegretta5beed502003-01-05 20:41:21 +00002409#ifndef NANO_SMALL
2410 /* for history */
2411 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00002412 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00002413 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002414 int last_kbinput = 0;
2415
2416 /* This variable is used in the search history code. use_cb == 0
2417 means that we're using the existing history and ignoring
2418 currentbuf. use_cb == 1 means that the entry in answer should be
2419 moved to currentbuf or restored from currentbuf to answer.
2420 use_cb == 2 means that the entry in currentbuf should be moved to
2421 answer or restored from answer to currentbuf. */
2422 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002423#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002424 statusbar_xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002425
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002426 /* Only put statusbar_x at the end of the string if it's
2427 * uninitialized, if it would be past the end of the string as it
2428 * is, or if resetstatuspos is TRUE. Otherwise, leave it alone.
2429 * This is so the cursor position stays at the same place if a
2430 * prompt-changing toggle is pressed. */
2431 if (statusbar_x == (size_t)-1 || statusbar_x > statusbar_xend ||
2432 resetstatuspos)
2433 statusbar_x = statusbar_xend;
Chris Allegretta09fc4302003-01-16 22:16:38 +00002434
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002435 answer = charealloc(answer, statusbar_xend + 1);
2436 if (statusbar_xend > 0)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002437 strcpy(answer, def);
2438 else
2439 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002440
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002441 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002442
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002443 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00002444
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002445 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002446
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002447 /* Refresh the edit window before getting input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002448 wnoutrefresh(edit);
2449 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002450
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002451 /* If we're using restricted mode, we aren't allowed to change the
2452 * name of a file once it has one because that would allow writing
2453 * to files not specified on the command line. In this case,
2454 * disable all keys that would change the text if the filename isn't
2455 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002456 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002457 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002458 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002459
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002460 /* If we have a shortcut with an associated function, break out
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002461 * if we're finished after running or trying to run the
2462 * function. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002463 if (finished)
2464 break;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002465
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002466 assert(statusbar_x <= statusbar_xend &&
2467 statusbar_xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002468
Chris Allegretta04d848e2000-11-05 17:54:41 +00002469 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002470 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00002471
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002472 switch (kbinput) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002473 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002474#ifndef NANO_SMALL
2475 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00002476 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002477 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002478 history_list->current = (historytype *)history_list;
2479 history_list->len = strlen(answer);
2480 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002481
Chris Allegretta7662c862003-01-13 01:35:15 +00002482 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002483 complete = get_history_completion(history_list, answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002484 statusbar_x = strlen(complete);
2485 statusbar_xend = statusbar_x;
Chris Allegretta5beed502003-01-05 20:41:21 +00002486 answer = mallocstrcpy(answer, complete);
2487 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002488 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002489#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002490 else
2491#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002492#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002493#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002494 if (allow_tabs) {
David Lawrence Ramsey65e6ecb2005-02-08 20:37:53 +00002495 answer = input_tab(answer, &statusbar_x, &tabbed, list);
David Lawrence Ramsey2724c882005-02-11 16:23:56 +00002496 statusbar_xend = strlen(answer);
Chris Allegretta5beed502003-01-05 20:41:21 +00002497 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002498 break;
David Lawrence Ramsey65e6ecb2005-02-08 20:37:53 +00002499#endif
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002500 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002501#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002502 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002503
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002504 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2505 isn't NULL, and currentbuf is different from answer,
2506 it means that we're scrolling up at the top of the
2507 search history, and we need to save the current
2508 answer in currentbuf; do this and reset use_cb to
2509 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002510 if (currentbuf == NULL || (use_cb == 1 &&
2511 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002512 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002513 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002514 }
2515
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002516 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2517 is different from answer, it means that we're
2518 scrolling up at the bottom of the search history, and
2519 we need to make the string in currentbuf the current
2520 answer; do this, blow away currentbuf since we don't
2521 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002522 if (currentbuf != NULL && use_cb == 2 &&
2523 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002524 answer = mallocstrcpy(answer, currentbuf);
2525 free(currentbuf);
2526 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002527 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002528 use_cb = 0;
2529
2530 /* else get older search from the history list and save
2531 it in answer; if there is no older search, blank out
2532 answer */
2533 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002534 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002535 statusbar_xend = strlen(history);
Chris Allegretta5beed502003-01-05 20:41:21 +00002536 } else {
2537 answer = mallocstrcpy(answer, "");
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002538 statusbar_xend = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002539 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002540 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002541 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002542#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002543 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002544 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002545#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002546 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002547
2548 /* get newer search from the history list and save it
2549 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002550 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002551 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002552 statusbar_xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002553
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002554 /* if there is no newer search, we're here */
2555
2556 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2557 that we're scrolling down at the bottom of the search
2558 history and we need to make the string in currentbuf
2559 the current answer; do this, blow away currentbuf
2560 since we don't need it anymore, and set use_cb to
2561 1 */
2562 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002563 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002564 free(currentbuf);
2565 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002566 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002567 use_cb = 1;
2568
2569 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2570 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002571 the search history and the current answer (if it's
2572 not blank) needs to be saved in currentbuf; do this,
2573 blank out answer (if necessary), and set use_cb to
2574 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002575 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002576 if (answer[0] != '\0') {
2577 currentbuf = mallocstrcpy(currentbuf, answer);
2578 answer = mallocstrcpy(answer, "");
2579 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002580 statusbar_xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002581 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002582 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002583 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002584 }
2585#endif
2586 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002587 }
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002588#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002589 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002590#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002591 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002592 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002593 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002594
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002595 /* We finished putting in an answer or ran a normal shortcut's
2596 * associated function, so reset statusbar_x. */
2597 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
2598 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002599 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002600
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002601 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002602}
2603
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002604/* Ask a question on the statusbar. Answer will be stored in answer
2605 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2606 * otherwise, the valid shortcut key caught. def is any editable text
2607 * we want to put up by default.
2608 *
2609 * New arg tabs tells whether or not to allow tab completion. */
2610int statusq(bool allow_tabs, const shortcut *s, const char *def,
2611#ifndef NANO_SMALL
2612 historyheadtype *which_history,
2613#endif
2614 const char *msg, ...)
2615{
2616 va_list ap;
2617 char *foo = charalloc(COLS - 3);
2618 int ret;
2619#ifndef DISABLE_TABCOMP
2620 bool list = FALSE;
2621#endif
2622
2623 bottombars(s);
2624
2625 va_start(ap, msg);
2626 vsnprintf(foo, COLS - 4, msg, ap);
2627 va_end(ap);
2628 foo[COLS - 4] = '\0';
2629
2630 ret = nanogetstr(allow_tabs, foo, def,
2631#ifndef NANO_SMALL
2632 which_history,
2633#endif
2634 s
2635#ifndef DISABLE_TABCOMP
2636 , &list
2637#endif
2638 );
2639 free(foo);
2640 resetstatuspos = FALSE;
2641
2642 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002643 case NANO_CANCEL_KEY:
2644 ret = -1;
2645 resetstatuspos = TRUE;
2646 break;
2647 case NANO_ENTER_KEY:
2648 ret = (answer[0] == '\0') ? -2 : 0;
2649 resetstatuspos = TRUE;
2650 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002651 }
2652 blank_statusbar();
2653
2654#ifdef DEBUG
2655 fprintf(stderr, "I got \"%s\"\n", answer);
2656#endif
2657
2658#ifndef DISABLE_TABCOMP
2659 /* if we've done tab completion, there might be a list of
2660 filename matches on the edit window at this point; make sure
2661 they're cleared off. */
2662 if (list)
2663 edit_refresh();
2664#endif
2665
2666 return ret;
2667}
2668
2669void statusq_abort(void)
2670{
2671 resetstatuspos = TRUE;
2672}
2673
Chris Allegrettaf717f982003-02-13 22:25:01 +00002674void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002675{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002676 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002677 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002678 size_t verlen = strlenpt(VERMSG) + 1;
2679 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002680 const char *prefix;
2681 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2682 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002683 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002684 const char *state;
2685 /* "Modified", "View", or spaces the length of "Modified".
2686 * Tells the state of this buffer. */
2687 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002688 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002689 char *exppath = NULL;
2690 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002691 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002692 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002693 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002694 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002695
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002696 assert(path != NULL || filename != NULL);
2697 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002698
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002699 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002700
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002701 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002702
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002703 if (COLS <= 5 || COLS - 5 < verlen)
2704 space = 0;
2705 else {
2706 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002707 /* Reserve 2/3 of the screen plus one column for after the
2708 * version message. */
2709 if (space < COLS - (COLS / 3) + 1)
2710 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002711 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002712
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002713 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002714 /* The version message should only take up 1/3 of the screen
2715 * minus one column. */
2716 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002717 waddstr(topwin, " ");
2718 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002719
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002720 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002721 state = _("Modified");
2722 else if (path == NULL && ISSET(VIEW_MODE))
2723 state = _("View");
2724 else {
2725 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002726 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002727 state = &hblank[COLS - statelen];
2728 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002729 statelen = strnlenpt(state, COLS);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002730 /* We need a space before state. */
2731 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2732 statelen++;
2733
2734 assert(space >= 0);
2735 if (space == 0 || statelen >= space)
2736 goto the_end;
2737
2738#ifndef DISABLE_BROWSER
2739 if (path != NULL)
2740 prefix = _("DIR:");
2741 else
2742#endif
2743 if (filename[0] == '\0') {
2744 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002745 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002746 } else
2747 prefix = _("File:");
2748 assert(statelen < space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002749 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002750 /* If newfie is FALSE, we need a space after prefix. */
2751 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002752 prefixlen++;
2753
2754 if (path == NULL)
2755 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002756 if (space >= prefixlen + statelen)
2757 space -= prefixlen + statelen;
2758 else
2759 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002760 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002761 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002762 size_t lenpt = strlenpt(path), start_col;
2763
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002764 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002765
2766 if (dots) {
2767 start_col = lenpt - space + 3;
2768 space -= 3;
2769 } else
2770 start_col = 0;
2771
2772 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002773 }
2774
2775 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002776 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2777 /* The length of the expanded filename. */
2778
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002779 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002780 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002781 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002782 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002783 assert(strlenpt(prefix) + 1 == prefixlen);
2784
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002785 waddch(topwin, ' ');
2786 waddstr(topwin, exppath);
2787 }
2788 } else {
2789 /* We will say something like "File: ...ename". */
2790 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002791 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002792 goto the_end;
2793 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002794 waddnstr(topwin, "...", space + 3);
2795 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002796 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002797 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002798 }
2799
2800 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002801 free(exppath);
2802
2803 if (COLS <= 1 || statelen >= COLS - 1)
2804 mvwaddnstr(topwin, 0, 0, state, COLS);
2805 else {
2806 assert(COLS - statelen - 2 >= 0);
2807 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2808 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2809 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002810
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002811 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002812
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002813 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002814 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002815 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002816}
2817
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002818/* If modified is not already set, set it and update titlebar. */
2819void set_modified(void)
2820{
2821 if (!ISSET(MODIFIED)) {
2822 SET(MODIFIED);
2823 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002824 }
2825}
2826
2827void statusbar(const char *msg, ...)
2828{
2829 va_list ap;
2830
2831 va_start(ap, msg);
2832
2833 /* Curses mode is turned off. If we use wmove() now, it will muck
2834 * up the terminal settings. So we just use vfprintf(). */
2835 if (curses_ended) {
2836 vfprintf(stderr, msg, ap);
2837 va_end(ap);
2838 return;
2839 }
2840
2841 /* Blank out the line. */
2842 blank_statusbar();
2843
2844 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002845 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002846 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002847#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002848 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002849
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002850 UNSET(WHITESPACE_DISPLAY);
2851#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002852 bar = charalloc(COLS - 3);
2853 vsnprintf(bar, COLS - 3, msg, ap);
2854 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002855 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002856#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2857 if (old_whitespace)
2858 SET(WHITESPACE_DISPLAY);
2859#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002860 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002861 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002862 start_x = (COLS - foo_len - 4) / 2;
2863
2864 wmove(bottomwin, 0, start_x);
2865 wattron(bottomwin, A_REVERSE);
2866
2867 waddstr(bottomwin, "[ ");
2868 waddstr(bottomwin, foo);
2869 free(foo);
2870 waddstr(bottomwin, " ]");
2871 wattroff(bottomwin, A_REVERSE);
2872 wnoutrefresh(bottomwin);
2873 reset_cursor();
2874 wrefresh(edit);
2875 /* Leave the cursor at its position in the edit window, not
2876 * in the statusbar. */
2877 }
2878
2879 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002880 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002881}
2882
Chris Allegretta6232d662002-05-12 19:52:15 +00002883void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002884{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002885 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002886
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002887 if (ISSET(NO_HELP))
2888 return;
2889
Chris Allegretta6232d662002-05-12 19:52:15 +00002890 if (s == main_list) {
2891 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002892 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002893 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002894 slen = length_of_list(s);
2895
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002896 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002897 if (slen > MAIN_VISIBLE)
2898 slen = MAIN_VISIBLE;
2899 }
2900
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002901 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002902 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002903 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002904
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002905 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002906
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002907 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002908 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002909
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002910 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002911#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002912 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002913 keystr = _("Up");
2914 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002915#endif
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00002916 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002917
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002918 if (s->ctrlval == NANO_CONTROL_SPACE)
2919 strcpy(foo, "^ ");
2920 else if (s->ctrlval == NANO_CONTROL_8)
2921 strcpy(foo, "^?");
2922 /* Normal values. Assume that the shortcut has an
2923 * equivalent control key, meta key sequence, or both. */
2924 else if (s->ctrlval != NANO_NO_KEY)
2925 sprintf(foo, "^%c", s->ctrlval + 64);
2926 else if (s->metaval != NANO_NO_KEY)
2927 sprintf(foo, "M-%c", toupper(s->metaval));
2928
2929 keystr = foo;
2930#ifndef NANO_SMALL
2931 }
2932#endif
2933
2934 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002935 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002936 }
2937
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002938 wnoutrefresh(bottomwin);
2939 reset_cursor();
2940 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002941}
2942
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002943/* Write a shortcut key to the help area at the bottom of the window.
2944 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2945 * to write at most len characters, even if len is very small and
2946 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2947 * the whole string! We do not bother padding the entry with blanks. */
2948void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002949{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002950 size_t keystroke_len = strlenpt(keystroke) + 1;
2951
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002952 assert(keystroke != NULL && desc != NULL);
2953
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002954 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002955 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002956 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002957
2958 if (len > keystroke_len)
2959 len -= keystroke_len;
2960 else
2961 len = 0;
2962
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002963 if (len > 0) {
2964 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002965 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002966 }
2967}
2968
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002969/* And so start the display update routines. */
2970
2971#ifndef NDEBUG
2972int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002973{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002974 int check_line = 0;
2975 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002976
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002977 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
2978 check_line++;
2979 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002980}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002981#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00002982
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002983/* nano scrolls horizontally within a line in chunks. This function
2984 * returns the column number of the first character displayed in the
2985 * window when the cursor is at the given column. Note that
2986 * 0 <= column - get_page_start(column) < COLS. */
2987size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002988{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002989 assert(COLS > 0);
2990 if (column == 0 || column < COLS - 1)
2991 return 0;
2992 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002993 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002994 else if (COLS > 2)
2995 return column - (COLS - 2);
2996 else
2997 return column - (COLS - 1);
2998 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002999}
3000
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003001/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003002 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003003void reset_cursor(void)
3004{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003005 /* If we haven't opened any files yet, put the cursor in the top
3006 * left corner of the edit window and get out. */
3007 if (edittop == NULL || current == NULL) {
3008 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003009 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003010 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003011
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003012 current_y = current->lineno - edittop->lineno;
3013 if (current_y < editwinrows) {
3014 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003015 wmove(edit, current_y, x - get_page_start(x));
3016 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003017}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003018
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003019/* edit_add() takes care of the job of actually painting a line into the
3020 * edit window. fileptr is the line to be painted, at row yval of the
3021 * window. converted is the actual string to be written to the window,
3022 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003023 * characters. start is the column number of the first character of
3024 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003025 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003026void edit_add(const filestruct *fileptr, const char *converted, int
3027 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003028{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003029#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003030 size_t startpos = actual_x(fileptr->data, start);
3031 /* The position in fileptr->data of the leftmost character
3032 * that displays at least partially on the window. */
3033 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3034 /* The position in fileptr->data of the first character that is
3035 * completely off the window to the right.
3036 *
3037 * Note that endpos might be beyond the null terminator of the
3038 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003039#endif
3040
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003041 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003042 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003043
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003044 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003045 * just the text that needs it). */
3046 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003047
Chris Allegretta7dd77682001-12-08 19:52:28 +00003048#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00003049 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003050 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003051
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003052 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3053 int x_start;
3054 /* Starting column for mvwaddnstr. Zero-based. */
3055 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003056 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003057 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003058 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003059 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003060 regmatch_t startmatch; /* match position for start_regexp */
3061 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003062
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003063 if (tmpcolor->bright)
3064 wattron(edit, A_BOLD);
3065 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003066 /* Two notes about regexec(). Return value 0 means there is
3067 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003068 * after the match. */
3069
3070 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003071 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003072 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003073
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003074 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003075 * last match. Even though two matches may overlap, we
3076 * want to ignore them, so that we can highlight
3077 * C-strings correctly. */
3078 while (k < endpos) {
3079 /* Note the fifth parameter to regexec(). It says
3080 * not to match the beginning-of-line character
3081 * unless k is 0. If regexec() returns REG_NOMATCH,
3082 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003083 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003084 &startmatch, k == 0 ? 0 :
3085 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003086 break;
3087 /* Translate the match to the beginning of the line. */
3088 startmatch.rm_so += k;
3089 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003090 if (startmatch.rm_so == startmatch.rm_eo) {
3091 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00003092 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003093 } else if (startmatch.rm_so < endpos &&
3094 startmatch.rm_eo > startpos) {
3095 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003096 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003097 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003098 x_start = strnlenpt(fileptr->data,
3099 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003100
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003101 index = actual_x(converted, x_start);
3102
3103 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003104 strnlenpt(fileptr->data,
3105 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003106
3107 assert(0 <= x_start && 0 <= paintlen);
3108
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003109 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003110 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003111 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003112 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003113 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003114 } else {
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003115 /* This is a multi-line regexp. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003116 * First, we have to see if the beginning of the line is
3117 * colored by a start on an earlier line, and an end on
3118 * this line or later.
3119 *
3120 * We find the first line before fileptr matching the
3121 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003122 * end, then go to step two. Otherwise, find the next
3123 * line after start_line matching the end. If that line
3124 * is not before fileptr, then paint the beginning of
3125 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003126 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003127 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003128 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003129 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003130 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003131
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003132 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003133 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003134 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003135 /* If there is an end on this line, there is no need
3136 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003137 if (regexec(tmpcolor->end, start_line->data, 0,
3138 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003139 goto step_two;
3140 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003141 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003142 /* No start found, so skip to the next step. */
3143 if (start_line == NULL)
3144 goto step_two;
3145 /* Now start_line is the first line before fileptr
3146 * containing a start match. Is there a start on this
3147 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003148 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003149 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003150 start_col += startmatch.rm_so;
3151 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003152 if (regexec(tmpcolor->end, start_line->data +
3153 start_col + startmatch.rm_eo, 0, NULL,
3154 start_col + startmatch.rm_eo == 0 ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003155 REG_NOTBOL) == REG_NOMATCH)
3156 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003157 break;
3158 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003159 if (regexec(&tmpcolor->start, start_line->data +
3160 start_col, 1, &startmatch,
3161 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003162 /* No later start on this line. */
3163 goto step_two;
3164 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003165 /* Indeed, there is a start not followed on this line by
3166 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003167
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003168 /* We have already checked that there is no end before
3169 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003170 * the start at all? We don't paint unterminated
3171 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003172 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003173 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003174 regexec(tmpcolor->end, end_line->data, 1,
3175 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003176 end_line = end_line->next;
3177
3178 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003179 if (end_line == NULL || (end_line == fileptr &&
3180 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003181 goto step_two;
3182
3183 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003184 if (end_line != fileptr)
3185 /* If the start of fileptr is on a different line
3186 * from the end, paintlen is -1, meaning that
3187 * everything on the line gets painted. */
3188 paintlen = -1;
3189 else
3190 /* Otherwise, paintlen is the expanded location of
3191 * the end of the match minus the expanded location
3192 * of the beginning of the page. */
3193 paintlen = actual_x(converted,
3194 strnlenpt(fileptr->data, endmatch.rm_eo) -
3195 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003196
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003197 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003198
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003199 step_two:
3200 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003201 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003202
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003203 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003204 if (regexec(&tmpcolor->start,
3205 fileptr->data + start_col, 1, &startmatch,
3206 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
3207 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003208 /* No more starts on this line. */
3209 break;
3210 /* Translate the match to be relative to the
3211 * beginning of the line. */
3212 startmatch.rm_so += start_col;
3213 startmatch.rm_eo += start_col;
3214
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003215 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003216 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003217 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003218 x_start = strnlenpt(fileptr->data,
3219 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003220
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003221 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003222
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003223 if (regexec(tmpcolor->end,
3224 fileptr->data + startmatch.rm_eo, 1, &endmatch,
3225 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003226 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003227 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003228 endmatch.rm_so += startmatch.rm_eo;
3229 endmatch.rm_eo += startmatch.rm_eo;
3230 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003231 * appear on this page, and is the match more
3232 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003233 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003234 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003235 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003236 strnlenpt(fileptr->data,
3237 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003238
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003239 assert(0 <= x_start && x_start < COLS);
3240
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003241 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003242 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003243 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003244 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003245 /* There is no end on this line. But we haven't
3246 * yet looked for one on later lines. */
3247 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003248
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003249 while (end_line != NULL &&
3250 regexec(tmpcolor->end, end_line->data,
3251 0, NULL, 0) == REG_NOMATCH)
3252 end_line = end_line->next;
3253
3254 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003255 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003256
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003257 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003258 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003259 /* We painted to the end of the line, so
3260 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003261 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003262 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003263 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003264 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003265 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003266 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003267
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003268 wattroff(edit, A_BOLD);
3269 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
3270 } /* for tmpcolor in colorstrings */
3271 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003272#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003273
Chris Allegretta7dd77682001-12-08 19:52:28 +00003274#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003275 if (ISSET(MARK_ISSET)
3276 && (fileptr->lineno <= mark_beginbuf->lineno
3277 || fileptr->lineno <= current->lineno)
3278 && (fileptr->lineno >= mark_beginbuf->lineno
3279 || fileptr->lineno >= current->lineno)) {
3280 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003281
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003282 const filestruct *top;
3283 /* Either current or mark_beginbuf, whichever is first. */
3284 size_t top_x;
3285 /* current_x or mark_beginx, corresponding to top. */
3286 const filestruct *bot;
3287 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003288 int x_start;
3289 /* Starting column for mvwaddnstr. Zero-based. */
3290 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003291 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003292 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003293 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003294 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003295
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003296 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003297
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003298 if (top->lineno < fileptr->lineno || top_x < startpos)
3299 top_x = startpos;
3300 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3301 bot_x = endpos;
3302
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003303 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003304 if (top_x < endpos && bot_x > startpos) {
3305 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003306
3307 /* x_start is the expanded location of the beginning of the
3308 * mark minus the beginning of the page. */
3309 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003310
3311 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003312 /* If the end of the mark is off the page, paintlen is
3313 * -1, meaning that everything on the line gets
3314 * painted. */
3315 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003316 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003317 /* Otherwise, paintlen is the expanded location of the
3318 * end of the mark minus the expanded location of the
3319 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003320 paintlen = strnlenpt(fileptr->data, bot_x) -
3321 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003322
3323 /* If x_start is before the beginning of the page, shift
3324 * paintlen x_start characters to compensate, and put
3325 * x_start at the beginning of the page. */
3326 if (x_start < 0) {
3327 paintlen += x_start;
3328 x_start = 0;
3329 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003330
3331 assert(x_start >= 0 && x_start <= strlen(converted));
3332
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003333 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003334
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003335 if (paintlen > 0)
3336 paintlen = actual_x(converted + index, paintlen);
3337
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003338 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003339 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003340 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003341 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003342 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003343 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003344#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003345}
3346
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003347/* Just update one line in the edit buffer. This is basically a wrapper
3348 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003349 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003350 * If fileptr != current, then index is considered 0. The line will be
3351 * displayed starting with fileptr->data[index]. Likely args are
3352 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003353void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003354{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003355 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003356 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003357 char *converted;
3358 /* fileptr->data converted to have tabs and control characters
3359 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003360 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003361
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003362 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003363
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003364 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003365
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003366 /* We assume the line numbers are valid. Is that really true? */
3367 assert(line < 0 || line == check_linenumbers(fileptr));
3368
3369 if (line < 0 || line >= editwinrows)
3370 return;
3371
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003372 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003373 mvwaddstr(edit, line, 0, hblank);
3374
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003375 /* Next, convert variables that index the line to their equivalent
3376 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003377 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003378 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003379
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003380 /* Expand the line, replacing tabs with spaces, and control
3381 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003382 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003383
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003384 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003385 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003386 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003387
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003388 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003389 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003390 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003391 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003392}
3393
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003394/* Return a nonzero value if we need an update after moving
3395 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003396 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003397int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003398{
3399 return
3400#ifndef NANO_SMALL
3401 ISSET(MARK_ISSET) ||
3402#endif
3403 get_page_start(old_pww) != get_page_start(placewewant);
3404}
3405
3406/* Return a nonzero value if we need an update after moving vertically.
3407 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003408 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003409int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003410{
3411 return
3412#ifndef NANO_SMALL
3413 ISSET(MARK_ISSET) ||
3414#endif
3415 get_page_start(old_pww) != get_page_start(placewewant);
3416}
3417
3418/* Scroll the edit window in the given direction and the given number
3419 * of lines, and draw new lines on the blank lines left after the
3420 * scrolling. direction is the direction to scroll, either UP or DOWN,
3421 * and nlines is the number of lines to scroll. Don't redraw the old
3422 * topmost or bottommost line (where we assume current is) before
3423 * scrolling or draw the new topmost or bottommost line after scrolling
3424 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003425 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003426void edit_scroll(updown direction, int nlines)
3427{
3428 filestruct *foo;
3429 int i, scroll_rows = 0;
3430
3431 /* Scrolling less than one line or more than editwinrows lines is
3432 * redundant, so don't allow it. */
3433 if (nlines < 1 || nlines > editwinrows)
3434 return;
3435
3436 /* Move the top line of the edit window up or down (depending on the
3437 * value of direction) nlines lines. If there are fewer lines of
3438 * text than that left, move it to the top or bottom line of the
3439 * file (depending on the value of direction). Keep track of
3440 * how many lines we moved in scroll_rows. */
3441 for (i = nlines; i > 0; i--) {
3442 if (direction == UP) {
3443 if (edittop->prev == NULL)
3444 break;
3445 edittop = edittop->prev;
3446 scroll_rows--;
3447 } else {
3448 if (edittop->next == NULL)
3449 break;
3450 edittop = edittop->next;
3451 scroll_rows++;
3452 }
3453 }
3454
3455 /* Scroll the text on the screen up or down scroll_rows lines,
3456 * depending on the value of direction. */
3457 scrollok(edit, TRUE);
3458 wscrl(edit, scroll_rows);
3459 scrollok(edit, FALSE);
3460
3461 foo = edittop;
3462 if (direction != UP) {
3463 int slines = editwinrows - nlines;
3464 for (; slines > 0 && foo != NULL; slines--)
3465 foo = foo->next;
3466 }
3467
3468 /* And draw new lines on the blank top or bottom lines of the edit
3469 * window, depending on the value of direction. Don't draw the new
3470 * topmost or new bottommost line. */
3471 while (scroll_rows != 0 && foo != NULL) {
3472 if (foo->next != NULL)
3473 update_line(foo, 0);
3474 if (direction == UP)
3475 scroll_rows++;
3476 else
3477 scroll_rows--;
3478 foo = foo->next;
3479 }
3480}
3481
3482/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003483 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003484void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003485{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003486 int do_refresh = need_vertical_update(0) ||
3487 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003488 const filestruct *foo;
3489
3490 /* If either old_current or current is offscreen, refresh the screen
3491 * and get out. */
3492 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3493 edittop->lineno + editwinrows || current->lineno <
3494 edittop->lineno || current->lineno >= edittop->lineno +
3495 editwinrows) {
3496 edit_refresh();
3497 return;
3498 }
3499
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003500 /* Update old_current and current if we're not on the first page
3501 * and/or we're not on the same page as before. If the mark is on,
3502 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003503 foo = old_current;
3504 while (foo != current) {
3505 if (do_refresh)
3506 update_line(foo, 0);
3507#ifndef NANO_SMALL
3508 if (!ISSET(MARK_ISSET))
3509#endif
3510 break;
3511 if (foo->lineno > current->lineno)
3512 foo = foo->prev;
3513 else
3514 foo = foo->next;
3515 }
3516 if (do_refresh)
3517 update_line(current, current_x);
3518}
3519
Chris Allegretta6df90f52002-07-19 01:08:59 +00003520/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003521void edit_refresh(void)
3522{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003523 if (current->lineno < edittop->lineno ||
3524 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003525 /* Note that edit_update() changes edittop so that it's in range
3526 * of current. Thus, when it then calls edit_refresh(), there
3527 * is no danger of getting an infinite loop. */
3528 edit_update(
3529#ifndef NANO_SMALL
3530 ISSET(SMOOTHSCROLL) ? NONE :
3531#endif
3532 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003533 else {
3534 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003535 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003536
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003537#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003538 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003539#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003540
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003541 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003542 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003543 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003544 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003545 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003546 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003547 }
3548 while (nlines < editwinrows) {
3549 mvwaddstr(edit, nlines, 0, hblank);
3550 nlines++;
3551 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003552 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003553 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003554 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003555}
3556
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003557/* A nice generic routine to update the edit buffer. We keep current in
3558 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003559void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003560{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003561 filestruct *foo = current;
3562
Chris Allegretta6df90f52002-07-19 01:08:59 +00003563 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003564 /* If location is CENTER, we move edittop up (editwinrows / 2)
3565 * lines. This puts current at the center of the screen. If
3566 * location is NONE, we move edittop up current_y lines if
3567 * current_y is in range of the screen, 0 lines if current_y is
3568 * less than 0, or (editwinrows - 1) lines if current_y is
3569 * greater than (editwinrows - 1). This puts current at the
3570 * same place on the screen as before, or at the top or bottom
3571 * of the screen if edittop is beyond either. */
3572 int goal;
3573
3574 if (location == CENTER)
3575 goal = editwinrows / 2;
3576 else {
3577 goal = current_y;
3578
3579 /* Limit goal to (editwinrows - 1) lines maximum. */
3580 if (goal > editwinrows - 1)
3581 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003582 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003583
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003584 for (; goal > 0 && foo->prev != NULL; goal--)
3585 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003586 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003587
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003588 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003589 edit_refresh();
3590}
3591
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003592/* Ask a simple yes/no question, specified in msg, on the statusbar.
3593 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3594 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003595int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003596{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003597 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003598 const char *yesstr; /* String of yes characters accepted. */
3599 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003600 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003601
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003602 /* yesstr, nostr, and allstr are strings of any length. Each string
3603 * consists of all characters accepted as a valid character for that
3604 * value. The first value will be the one displayed in the
3605 * shortcuts. Translators: if possible, specify both the shortcuts
3606 * for your language and English. For example, in French: "OoYy"
3607 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003608 yesstr = _("Yy");
3609 nostr = _("Nn");
3610 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003611
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003612 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003613 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003614
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003615 if (COLS < 32)
3616 width = COLS / 2;
3617
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003618 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003619 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003620
Chris Allegretta6232d662002-05-12 19:52:15 +00003621 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003622 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003623 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003624
3625 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003626 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003627 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003628 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003629 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003630
Chris Allegrettadb28e962003-01-28 01:23:40 +00003631 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003632 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003633 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003634
Chris Allegrettadb28e962003-01-28 01:23:40 +00003635 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003636 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003637 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003638
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003639 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003640
3641 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003642 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003643
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003644 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003645
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003646 wrefresh(bottomwin);
3647
Chris Allegrettadb28e962003-01-28 01:23:40 +00003648 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003649 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003650 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003651#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003652 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003653#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003654
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003655 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003656
3657 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003658 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003659#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003660 /* Look, ma! We get to duplicate lots of code from
3661 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003662 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003663 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003664
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003665 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003666 wenclose(bottomwin, mouse_y, mouse_x) &&
3667 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003668 int x = mouse_x / width;
3669 /* Did we click in the first column of shortcuts, or
3670 * the second? */
3671 int y = mouse_y - editwinrows - 3;
3672 /* Did we click in the first row of shortcuts? */
3673
3674 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3675
3676 /* x = 0 means they clicked Yes or No.
3677 * y = 0 means Yes or All. */
3678 ok = -2 * x * y + x - y + 1;
3679
3680 if (ok == 2 && !all)
3681 ok = -2;
3682 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003683 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003684#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003685 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003686 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003687 else if (strchr(yesstr, kbinput) != NULL)
3688 ok = 1;
3689 else if (strchr(nostr, kbinput) != NULL)
3690 ok = 0;
3691 else if (all && strchr(allstr, kbinput) != NULL)
3692 ok = 2;
3693 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003694
Chris Allegrettadb28e962003-01-28 01:23:40 +00003695 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003696}
3697
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003698void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003699{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003700 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003701 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003702 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003703 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003704 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003705 wnoutrefresh(bottomwin);
3706 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003707 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003708 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003709 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003710 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003711 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003712 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003713}
3714
3715void display_main_list(void)
3716{
3717 bottombars(main_list);
3718}
3719
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003720/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3721 * display the cursor position. Otherwise, we display it only if the
3722 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003723 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003724 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3725 * old_i and old_totsize. That way, we leave the current statusbar
3726 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003727void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003728{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003729 char c;
3730 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003731 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003732 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003733
Chris Allegrettad26ab912003-01-28 01:16:47 +00003734 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003735
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003736 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003737 old_totsize = totsize;
3738
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003739 c = current->data[current_x];
3740 f = current->next;
3741 current->data[current_x] = '\0';
3742 current->next = NULL;
3743 get_totals(fileage, current, NULL, &i);
3744 current->data[current_x] = c;
3745 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003746
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003747 /* Check whether totsize is correct. Else there is a bug
3748 * somewhere. */
3749 assert(current != filebot || i == totsize);
3750
Chris Allegrettad26ab912003-01-28 01:16:47 +00003751 if (constant && ISSET(DISABLE_CURPOS)) {
3752 UNSET(DISABLE_CURPOS);
3753 old_i = i;
3754 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003755 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003756 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003757
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003758 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003759 * unconditionally; otherwise, only display the position when the
3760 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003761 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003762 size_t xpt = xplustabs() + 1;
3763 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003764 int linepct = 100 * current->lineno / totlines;
3765 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003766 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003767
3768 statusbar(
3769 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3770 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003771 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003772 (unsigned long)i, (unsigned long)totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003773 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003774 }
3775
3776 old_i = i;
3777 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003778}
3779
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003780void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003781{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003782 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003783}
3784
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003785#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003786/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003787int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003788{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003789 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003790
3791 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3792 ptr++;
3793 j++;
3794 }
3795 if (j == COLS - 5) {
3796 /* Don't wrap at the first of two spaces following a period. */
3797 if (*ptr == ' ' && *(ptr + 1) == ' ')
3798 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003799 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003800 while (*ptr != ' ' && j > 0) {
3801 ptr--;
3802 j--;
3803 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003804 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003805 if (j == 0)
3806 j = COLS - 5;
3807 }
3808 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
3809 return j;
3810}
3811
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003812/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003813void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003814{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003815 int line = 0;
3816 /* The line number in help_text of the first displayed help line.
3817 * This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003818 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003819 /* no_more means the end of the help text is shown, so don't go
3820 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003821 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003822 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003823
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003824 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003825#ifndef DISABLE_MOUSE
3826 const shortcut *oldshortcut = currshortcut;
3827 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003828 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003829#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003830
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003831 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003832 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003833 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003834 blank_statusbar();
3835
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003836 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003837 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003838 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003839
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003840#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003841 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003842 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003843 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003844#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003845
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003846 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003847 /* Make sure that the help screen's shortcut list will actually
3848 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003849 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003850 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003851 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003852
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003853 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003854
3855 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003856 int i;
3857 int old_line = line;
3858 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003859 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003860
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003861 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003862#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003863 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003864 {
3865 int mouse_x, mouse_y;
3866 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3867 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003868 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003869#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003870 case NANO_NEXTPAGE_KEY:
3871 case NANO_NEXTPAGE_FKEY:
3872 if (!no_more)
3873 line += editwinrows - 2;
3874 break;
3875 case NANO_PREVPAGE_KEY:
3876 case NANO_PREVPAGE_FKEY:
3877 if (line > 0) {
3878 line -= editwinrows - 2;
3879 if (line < 0)
3880 line = 0;
3881 }
3882 break;
3883 case NANO_PREVLINE_KEY:
3884 if (line > 0)
3885 line--;
3886 break;
3887 case NANO_NEXTLINE_KEY:
3888 if (!no_more)
3889 line++;
3890 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003891 }
3892
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003893 if (line == old_line && kbinput != ERR)
3894 goto skip_redisplay;
3895
3896 blank_edit();
3897
3898 assert(COLS > 5);
3899
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003900 /* Calculate where in the text we should be, based on the
3901 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003902 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003903 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003904 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003905 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003906 }
3907
Chris Allegretta4640fe32003-02-10 03:10:03 +00003908 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003909 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003910
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003911 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003912 ptr += j;
3913 if (*ptr == '\n')
3914 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003915 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003916 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003917
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003918 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003919 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003920 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3921 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003922
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003923#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003924 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003925#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003926
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003927 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003928 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003929 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003930 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003931 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003932 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003933 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003934
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003935 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003936 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003937
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003938 /* The help_init() at the beginning allocated help_text. Since
3939 * help_text has now been written to the screen, we don't need it
3940 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003941 free(help_text);
3942 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003943}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003944#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003945
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003946/* Highlight the current word being replaced or spell checked. We
3947 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003948void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003949{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003950 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003951 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003952
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003953 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003954 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003955 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003956
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003957 assert(y > 0);
3958
3959 if (word_len > y)
3960 y--;
3961
Chris Allegrettafb62f732000-12-05 11:36:41 +00003962 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003963
Chris Allegrettafb62f732000-12-05 11:36:41 +00003964 if (highlight_flag)
3965 wattron(edit, A_REVERSE);
3966
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003967#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003968 /* This is so we can show zero-length regexes. */
3969 if (word_len == 0)
3970 waddstr(edit, " ");
3971 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003972#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003973 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003974
3975 if (word_len > y)
3976 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003977
3978 if (highlight_flag)
3979 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003980}
3981
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003982#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003983/* Dump the passed-in file structure to stderr. */
3984void dump_buffer(const filestruct *inptr)
3985{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003986 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003987 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003988 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003989 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003990 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003991 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003992
3993 while (inptr != NULL) {
3994 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
3995 inptr = inptr->next;
3996 }
3997}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003998
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003999/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004000void dump_buffer_reverse(void)
4001{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004002 const filestruct *fileptr = filebot;
4003
4004 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004005 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004006 fileptr = fileptr->prev;
4007 }
4008}
4009#endif /* DEBUG */
4010
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004011#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004012#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004013#define XLCREDIT_LEN 8
4014
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004015/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004016void do_credits(void)
4017{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004018 int crpos = 0, xlpos = 0;
4019 const char *credits[CREDIT_LEN] = {
4020 NULL, /* "The nano text editor" */
4021 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004022 VERSION,
4023 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004024 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004025 "Chris Allegretta",
4026 "Jordi Mallach",
4027 "Adam Rogoyski",
4028 "Rob Siemborski",
4029 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004030 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004031 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004032 "Ken Tyler",
4033 "Sven Guckes",
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004034#ifdef NANO_WIDE
David Lawrence Ramsey487d08c2005-01-12 18:16:17 +00004035 !ISSET(NO_UTF8) ? "Florian König" :
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004036#endif
4037 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00004038 "Pauli Virtanen",
4039 "Daniele Medri",
4040 "Clement Laforet",
4041 "Tedi Heriyanto",
4042 "Bill Soudan",
4043 "Christian Weisgerber",
4044 "Erik Andersen",
4045 "Big Gaute",
4046 "Joshua Jensen",
4047 "Ryan Krebs",
4048 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004049 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004050 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004051 "Plattsburgh State University",
4052 "Benet Laboratories",
4053 "Amy Allegretta",
4054 "Linda Young",
4055 "Jeremy Robichaud",
4056 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004057 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004058 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004059 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004060 "Thomas Dickey",
4061 "Pavel Curtis",
4062 "Zeyd Ben-Halim",
4063 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004064 NULL, /* "and anyone else we forgot..." */
4065 NULL, /* "Thank you for using nano!" */
4066 "",
4067 "",
4068 "",
4069 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004070 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004071 "",
4072 "",
4073 "",
4074 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004075 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004076 };
4077
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004078 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004079 N_("The nano text editor"),
4080 N_("version"),
4081 N_("Brought to you by:"),
4082 N_("Special thanks to:"),
4083 N_("The Free Software Foundation"),
4084 N_("For ncurses:"),
4085 N_("and anyone else we forgot..."),
4086 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004087 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004088
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004089 curs_set(0);
4090 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004091 scrollok(edit, TRUE);
4092 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004093 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004094 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004095 blank_statusbar();
4096 blank_bottombars();
4097 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004098 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004099 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004100
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004101 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
4102 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004103 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004104 if (crpos < CREDIT_LEN) {
4105 const char *what = credits[crpos];
4106 size_t start_x;
4107
4108 if (what == NULL) {
4109 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00004110 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004111 xlpos++;
4112 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004113 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramseyeb711b02004-12-05 22:24:39 +00004114 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x,
4115 what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004116 }
4117 napms(700);
4118 scroll(edit);
4119 wrefresh(edit);
4120 if (wgetch(edit) != ERR)
4121 break;
4122 napms(700);
4123 scroll(edit);
4124 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004125 }
4126
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004127 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004128 nodelay(edit, FALSE);
4129 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004130 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004131}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004132#endif