blob: 440b6c556190543b0b8e6221e62a72de307e16c4 [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. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000047static bool resetstatuspos = FALSE;
48 /* Should we reset the cursor position
49 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000050
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000051/* Control character compatibility:
52 *
53 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
54 * VT100, and VT220.
55 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
56 * VT220, and VT320.
57 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
58 * VT220, and VT320.
59 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
60 * VT220, and VT320.
61 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
62 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000063 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000064 * ANSI, VT100, and VT220, and which is Backspace under VT320.
65 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000066 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000067 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
68 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000069 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000070 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000071 * on which the VT320 sequences are translated by the keypad to KEY_DC
72 * and [nothing]. We work around this conflict via the REBIND_DELETE
73 * flag: if it's not set, we assume VT320 compatibility, and if it is,
74 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
75 * Hemel for helping work this conflict out.
76 *
77 * Escape sequence compatibility:
78 *
79 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000080 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000081 * console), xterm, rxvt, and Eterm. Among these, there are several
82 * conflicts and omissions, outlined as follows:
83 *
84 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
85 * (Ctrl-I is also Tab on ANSI, which we already support.)
86 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
87 * NumLock off on Linux console; the latter is omitted. (The editing
88 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000089 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000090 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
91 * latter is omitted. (Mouse input will only work properly if the
92 * extended keypad value KEY_MOUSE is generated on mouse events
93 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000094 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000095 * omitted. (The editing keypad is more important to have working
96 * than the function keys, because the functions of the former are not
97 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000098 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000099 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000100 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000101 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000102 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
103 * omitted. (The arrow keys, with or without modifiers, are more
104 * important to have working than the function keys, because the
105 * functions of the former are not arbitrary and the functions of the
106 * latter are.)
107 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
108 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000109 *
110 * Note that Center (5) on the numeric keypad with NumLock off can also
111 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000112
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000113#ifndef NANO_SMALL
114/* Reset all the input routines that rely on character sequences. */
115void reset_kbinput(void)
116{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000117 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000118 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000119 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000120}
121#endif
122
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000123/* Read in a sequence of keystrokes from win and save them in the
124 * default keystroke buffer. This should only be called when the
125 * default keystroke buffer is empty. */
126void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000127{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000128 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000129
130 /* If the keystroke buffer isn't empty, get out. */
131 if (key_buffer != NULL)
132 return;
133
134 /* Read in the first character using blocking input. */
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000135#ifndef NANO_SMALL
136 allow_pending_sigwinch(TRUE);
137#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000138
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000139 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000140
David Lawrence Ramseyc275dc52005-03-08 17:45:36 +0000141 /* If we get ERR when using blocking input, it means that the input
142 * source that we were using is gone, so die gracefully. */
143 if (input == ERR)
144 handle_hupterm(0);
145
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000146#ifndef NANO_SMALL
147 allow_pending_sigwinch(FALSE);
148#endif
149
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000150 /* Increment the length of the keystroke buffer, save the value of
151 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000152 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000153 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000154 key_buffer = (int *)nmalloc(sizeof(int));
155 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000156
157 /* Read in the remaining characters using non-blocking input. */
158 nodelay(win, TRUE);
159
160 while (TRUE) {
161#ifndef NANO_SMALL
162 allow_pending_sigwinch(TRUE);
163#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000164
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000165 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000166
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000167 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000168 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000169 break;
170
171 /* Otherwise, increment the length of the keystroke buffer, save
172 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000173 * if the keystroke is an extended keypad value or FALSE if it
174 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000175 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000176 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
177 sizeof(int));
178 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000179
180#ifndef NANO_SMALL
181 allow_pending_sigwinch(FALSE);
182#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000183 }
184
185 /* Switch back to non-blocking input. */
186 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000187}
188
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000189/* Return the length of the default keystroke buffer. */
190size_t get_buffer_len(void)
191{
192 return key_buffer_len;
193}
194
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000195/* Add the contents of the keystroke buffer input to the default
196 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000197void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000198{
199#ifndef NANO_SMALL
200 allow_pending_sigwinch(TRUE);
201 allow_pending_sigwinch(FALSE);
202#endif
203
204 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000205 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000206 return;
207
208 /* If adding input would put the default keystroke buffer beyond
209 * maximum capacity, only add enough of input to put it at maximum
210 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000211 if (key_buffer_len + input_len < key_buffer_len)
212 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000213
214 /* Add the length of input to the length of the default keystroke
215 * buffer, and reallocate the default keystroke buffer so that it
216 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000217 key_buffer_len += input_len;
218 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
219 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000220
221 /* If the default keystroke buffer wasn't empty before, move its
222 * beginning forward far enough so that we can add input to its
223 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000224 if (key_buffer_len > input_len)
225 memmove(key_buffer + input_len, key_buffer,
226 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000227
228 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000229 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000230}
231
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000232/* Put back the character stored in kbinput, putting it in byte range
233 * beforehand. If meta_key is TRUE, put back the Escape character after
234 * putting back kbinput. If func_key is TRUE, put back the function key
235 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000236void unget_kbinput(int kbinput, bool meta_key, bool func_key)
237{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000238 if (!func_key)
239 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000240
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000241 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000242
243 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000244 kbinput = NANO_CONTROL_3;
245 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000246 }
247}
248
249/* Try to read input_len characters from the default keystroke buffer.
250 * If the default keystroke buffer is empty and win isn't NULL, try to
251 * read in more characters from win and add them to the default
252 * keystroke buffer before doing anything else. If the default
253 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000254int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000255{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000256 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000257
258#ifndef NANO_SMALL
259 allow_pending_sigwinch(TRUE);
260 allow_pending_sigwinch(FALSE);
261#endif
262
263 if (key_buffer_len == 0) {
264 if (win != NULL)
265 get_buffer(win);
266
267 if (key_buffer_len == 0)
268 return NULL;
269 }
270
271 /* If input_len is greater than the length of the default keystroke
272 * buffer, only read the number of characters in the default
273 * keystroke buffer. */
274 if (input_len > key_buffer_len)
275 input_len = key_buffer_len;
276
277 /* Subtract input_len from the length of the default keystroke
278 * buffer, and allocate the keystroke buffer input so that it
279 * has enough room for input_len keystrokes. */
280 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000281 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000282
283 /* Copy input_len characters from the beginning of the default
284 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000285 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000286
287 /* If the default keystroke buffer is empty, mark it as such. */
288 if (key_buffer_len == 0) {
289 free(key_buffer);
290 key_buffer = NULL;
291 /* If the default keystroke buffer isn't empty, move its
292 * beginning forward far enough back so that the keystrokes in input
293 * are no longer at its beginning. */
294 } else {
295 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000296 sizeof(int));
297 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
298 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000299 }
300
301 return input;
302}
303
304/* Read in a single character. If it's ignored, swallow it and go on.
305 * Otherwise, try to translate it from ASCII, meta key sequences, escape
306 * sequences, and/or extended keypad values. Set meta_key to TRUE when
307 * we get a meta key sequence, and set func_key to TRUE when we get an
308 * extended keypad value. Supported extended keypad values consist of
309 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
310 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
311 * the function keypad (F1-F16), and the numeric keypad with NumLock
312 * off. Assume nodelay(win) is FALSE. */
313int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
314{
315 int kbinput;
316
317 /* Read in a character and interpret it. Continue doing this until
318 * we get a recognized value or sequence. */
319 while ((kbinput = parse_kbinput(win, meta_key, func_key
320#ifndef NANO_SMALL
321 , FALSE
322#endif
323 )) == ERR);
324
325 return kbinput;
326}
327
328/* Translate ASCII characters, extended keypad values, and escape
329 * sequences into their corresponding key values. Set meta_key to TRUE
330 * when we get a meta key sequence, and set func_key to TRUE when we get
331 * a function key. Assume nodelay(win) is FALSE. */
332int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000333#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000334 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000335#endif
336 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000337
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000338{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000339 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000340 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000341
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000342#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000343 if (reset) {
344 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000345 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000346 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000347 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000348#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000349
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000350 *meta_key = FALSE;
351 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000352
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000353 /* Read in a character. */
354 while ((kbinput = get_input(win, 1)) == NULL);
355
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000356 switch (*kbinput) {
357 case ERR:
358 break;
359 case NANO_CONTROL_3:
360 /* Increment the escape counter. */
361 escapes++;
362 switch (escapes) {
363 case 1:
364 /* One escape: wait for more input. */
365 case 2:
366 /* Two escapes: wait for more input. */
367 break;
368 default:
369 /* More than two escapes: reset the escape counter
370 * and wait for more input. */
371 escapes = 0;
372 }
373 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000374#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000375 /* Since we don't change the default SIGWINCH handler when
376 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
377 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
378 case KEY_RESIZE:
379 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000380#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000381#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000382 case KEY_SHIFT_L:
383 case KEY_SHIFT_R:
384 case KEY_CONTROL_L:
385 case KEY_CONTROL_R:
386 case KEY_ALT_L:
387 case KEY_ALT_R:
388 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000389#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000390 default:
391 switch (escapes) {
392 case 0:
393 switch (*kbinput) {
394 case NANO_CONTROL_8:
395 retval = ISSET(REBIND_DELETE) ?
396 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
397 break;
398 case KEY_DOWN:
399 retval = NANO_NEXTLINE_KEY;
400 break;
401 case KEY_UP:
402 retval = NANO_PREVLINE_KEY;
403 break;
404 case KEY_LEFT:
405 retval = NANO_BACK_KEY;
406 break;
407 case KEY_RIGHT:
408 retval = NANO_FORWARD_KEY;
409 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000410#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000411 /* HP-UX 10 and 11 don't support KEY_HOME. */
412 case KEY_HOME:
413 retval = NANO_HOME_KEY;
414 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000415#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000416 case KEY_BACKSPACE:
417 retval = NANO_BACKSPACE_KEY;
418 break;
419 case KEY_DC:
420 retval = ISSET(REBIND_DELETE) ?
421 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
422 break;
423 case KEY_IC:
424 retval = NANO_INSERTFILE_KEY;
425 break;
426 case KEY_NPAGE:
427 retval = NANO_NEXTPAGE_KEY;
428 break;
429 case KEY_PPAGE:
430 retval = NANO_PREVPAGE_KEY;
431 break;
432 case KEY_ENTER:
433 retval = NANO_ENTER_KEY;
434 break;
435 case KEY_A1: /* Home (7) on numeric keypad
436 * with NumLock off. */
437 retval = NANO_HOME_KEY;
438 break;
439 case KEY_A3: /* PageUp (9) on numeric keypad
440 * with NumLock off. */
441 retval = NANO_PREVPAGE_KEY;
442 break;
443 case KEY_B2: /* Center (5) on numeric keypad
444 * with NumLock off. */
445 break;
446 case KEY_C1: /* End (1) on numeric keypad
447 * with NumLock off. */
448 retval = NANO_END_KEY;
449 break;
450 case KEY_C3: /* PageDown (4) on numeric
451 * keypad with NumLock off. */
452 retval = NANO_NEXTPAGE_KEY;
453 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000454#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000455 /* Slang doesn't support KEY_BEG. */
456 case KEY_BEG: /* Center (5) on numeric keypad
457 * with NumLock off. */
458 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000459#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000460#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000461 /* HP-UX 10 and 11 don't support KEY_END. */
462 case KEY_END:
463 retval = NANO_END_KEY;
464 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000465#endif
466#ifdef KEY_SUSPEND
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000467 /* Slang doesn't support KEY_SUSPEND. */
468 case KEY_SUSPEND:
469 retval = NANO_SUSPEND_KEY;
470 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000471#endif
472#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000473 /* Slang doesn't support KEY_SLEFT. */
474 case KEY_SLEFT:
475 retval = NANO_BACK_KEY;
476 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000477#endif
478#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000479 /* Slang doesn't support KEY_SRIGHT. */
480 case KEY_SRIGHT:
481 retval = NANO_FORWARD_KEY;
482 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000483#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000484 default:
485 retval = *kbinput;
486 break;
487 }
488 break;
489 case 1:
490 /* One escape followed by a non-escape: escape
491 * sequence mode. Reset the escape counter. If
492 * there aren't any other keys waiting, we have a
493 * meta key sequence, so set meta_key to TRUE and
494 * save the lowercase version of the non-escape
495 * character as the result. If there are other keys
496 * waiting, we have a true escape sequence, so
497 * interpret it. */
498 escapes = 0;
499 if (get_buffer_len() == 0) {
500 *meta_key = TRUE;
501 retval = tolower(*kbinput);
502 } else {
503 int *seq;
504 size_t seq_len;
505 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000506
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000507 /* Put back the non-escape character, get the
508 * complete escape sequence, translate the
509 * sequence into its corresponding key value,
510 * and save that as the result. */
511 unget_input(kbinput, 1);
512 seq_len = get_buffer_len();
513 seq = get_input(NULL, seq_len);
514 retval = get_escape_seq_kbinput(seq, seq_len,
515 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000516
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000517 /* If the escape sequence is unrecognized and
518 * not ignored, put back all of its characters
519 * except for the initial escape. */
520 if (retval == ERR && !ignore_seq)
521 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000522
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000523 free(seq);
524 }
525 break;
526 case 2:
527 /* Two escapes followed by one or more decimal
528 * digits: byte sequence mode. If the word
529 * sequence's range is limited to 2XX (the first
530 * digit is in the '0' to '2' range and it's the
531 * first digit, or it's in the '0' to '9' range and
532 * it's not the first digit), increment the byte
533 * sequence counter and interpret the digit. If the
534 * byte sequence's range is not limited to 2XX, fall
535 * through. */
536 if (('0' <= *kbinput && *kbinput <= '6' &&
537 byte_digits == 0) || ('0' <= *kbinput &&
538 *kbinput <= '9' && byte_digits > 0)) {
539 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000540
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000541 byte_digits++;
542 byte = get_byte_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000543#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000544 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000545#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000546 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000547
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000548 if (byte != ERR) {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +0000549 char *byte_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000550 int byte_mb_len, *seq, i;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000551
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000552 /* If we've read in a complete byte
553 * sequence, reset the byte sequence counter
554 * and the escape counter, and put back the
555 * corresponding byte value. */
556 byte_digits = 0;
557 escapes = 0;
558
559 /* Put back the multibyte equivalent of the
560 * byte value. */
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +0000561 byte_mb = make_mbchar(byte, &byte_mb_len);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000562
563 seq = (int *)nmalloc(byte_mb_len *
564 sizeof(int));
565
566 for (i = 0; i < byte_mb_len; i++)
567 seq[i] = (unsigned char)byte_mb[i];
568
569 unget_input(seq, byte_mb_len);
570
571 free(seq);
572 free(byte_mb);
573 }
574 } else {
575 /* Reset the escape counter. */
576 escapes = 0;
577 if (byte_digits == 0)
578 /* Two escapes followed by a non-decimal
579 * digit or a decimal digit that would
580 * create a byte sequence greater than 2XX,
581 * and we're not in the middle of a byte
582 * sequence: control character sequence
583 * mode. Interpret the control sequence and
584 * save the corresponding control character
585 * as the result. */
586 retval = get_control_kbinput(*kbinput);
587 else {
588 /* If we're in the middle of a byte
589 * sequence, reset the byte sequence counter
590 * and save the character we got as the
591 * result. */
592 byte_digits = 0;
593 retval = *kbinput;
594 }
595 }
596 break;
597 }
598 }
599
600 /* If we have a result and it's an extended keypad value (i.e, a
601 * value outside of byte range), set func_key to TRUE. */
602 if (retval != ERR)
603 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000604
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000605#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000606 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 +0000607#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000608
609 /* Return the result. */
610 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000611}
612
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000613/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000614 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000615 * are generated when the keypad doesn't support the needed keys. If
616 * the escape sequence is recognized but we want to ignore it, return
617 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
618 * set ignore_seq to FALSE. Assume that Escape has already been read
619 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000620int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000621 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000622{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000623 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000624
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000625 *ignore_seq = FALSE;
626
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000627 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000628 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000629 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000630 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000631 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000632 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000633 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000634 case 'P': /* Esc O 2 P == F13 on
635 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000636 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000637 break;
638 case 'Q': /* Esc O 2 Q == F14 on
639 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000640 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000641 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000642 case 'R': /* Esc O 2 R == F15 on
643 * xterm. */
644 retval = KEY_F(15);
645 break;
646 case 'S': /* Esc O 2 S == F16 on
647 * xterm. */
648 retval = KEY_F(16);
649 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000650 }
651 }
652 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000653 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
654 case 'B': /* Esc O B == Down on
655 * VT100/VT320/xterm. */
656 case 'C': /* Esc O C == Right on
657 * VT100/VT320/xterm. */
658 case 'D': /* Esc O D == Left on
659 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000660 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000661 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000662 case 'E': /* Esc O E == Center (5) on numeric keypad
663 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000664 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000665 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000666 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000667 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000668 break;
669 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000670 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000671 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000672 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000673 * NumLock off on VT100/VT220/VT320/xterm/
674 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000675 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000676 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000677 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000678 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000679 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000680 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000681 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000682 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000683 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000684 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000685 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000686 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000687 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000688 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000689 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000690 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000691 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000692 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000693 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000694 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000695 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000696 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000697 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000698 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000699 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000700 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000701 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000702 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000703 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000704 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000705 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000706 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000707 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000708 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000709 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000710 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000711 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000712 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000713 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000714 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000715 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000716 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000717 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000718 * NumLock off on VT100/VT220/VT320/xterm/
719 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000720 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000721 break;
722 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000723 * NumLock off on VT100/VT220/VT320/xterm/
724 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000725 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000726 break;
727 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000728 * NumLock off on VT100/VT220/VT320/xterm/
729 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000730 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000731 break;
732 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000733 * NumLock off on VT100/VT220/VT320/xterm/
734 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000735 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000736 break;
737 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000738 * with NumLock off on VT100/VT220/VT320/
739 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000740 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000741 break;
742 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000743 * NumLock off on VT100/VT220/VT320/xterm/
744 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000745 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000746 break;
747 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000748 * with NumLock off on VT100/VT220/VT320/
749 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000750 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000751 break;
752 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000753 * with NumLock off on VT100/VT220/VT320/
754 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000755 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000756 break;
757 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000758 * with NumLock off on VT100/VT220/VT320/
759 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000760 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000761 break;
762 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000763 * keypad with NumLock off on VT100/VT220/
764 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000765 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000766 break;
767 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000768 * with NumLock off on VT100/VT220/VT320/
769 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000770 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000771 break;
772 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000773 * with NumLock off on VT100/VT220/VT320/
774 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000775 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000776 break;
777 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000778 * with NumLock off on VT100/VT220/VT320/
779 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000780 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000781 break;
782 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000783 * with NumLock off on VT100/VT220/VT320/
784 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000785 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000786 break;
787 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000788 * with NumLock off on VT100/VT220/VT320/
789 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000790 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000791 break;
792 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000793 * with NumLock off on VT100/VT220/VT320/
794 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000795 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000796 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000797 }
798 break;
799 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000800 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000801 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000802 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000803 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000804 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000805 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000806 break;
807 }
808 break;
809 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000810 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000811 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000812 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000813 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000814 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
815 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000816 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000817 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000818 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
819 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000820 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000821 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000822 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
823 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000824 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000825 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000826 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
827 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000828 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000829 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000830 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
831 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000832 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000833 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000834 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000835 * VT220/VT320/Linux console/
836 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000837 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000838 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000839 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000840 * VT220/VT320/Linux console/
841 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000842 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000843 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000844 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000845 * VT220/VT320/Linux console/
846 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000847 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000848 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000849 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000850 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000851 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000852 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000853 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000854 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000855 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
856 * xterm. */
857 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
858 * xterm. */
859 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
860 * xterm. */
861 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
862 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000863 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000864 break;
865 }
866 }
867 break;
868 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000869 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000870 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000871 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
872 * xterm. */
873 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
874 * xterm. */
875 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
876 * xterm. */
877 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
878 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000879 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000880 break;
881 }
882 }
883 break;
884 }
885 }
886 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000887 default: /* Esc [ 1 ~ == Home on
888 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000889 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000890 break;
891 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000892 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000893 break;
894 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000895 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000896 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000897 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000898 * VT220/VT320/Linux console/
899 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000900 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000901 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000902 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000903 * VT220/VT320/Linux console/
904 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000905 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000906 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000907 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000908 * VT220/VT320/Linux console/
909 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000910 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000911 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000912 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000913 * VT220/VT320/Linux console/
914 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000915 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000916 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000917 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000918 * VT220/VT320/Linux console/
919 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000920 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000921 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000922 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000923 * VT220/VT320/Linux console/
924 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000925 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000926 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000927 case '8': /* Esc [ 2 8 ~ == F15 on
928 * VT220/VT320/Linux console/
929 * rxvt/Eterm. */
930 retval = KEY_F(15);
931 break;
932 case '9': /* Esc [ 2 9 ~ == F16 on
933 * VT220/VT320/Linux console/
934 * rxvt/Eterm. */
935 retval = KEY_F(16);
936 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000937 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000938 * VT220/VT320/Linux console/
939 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000940 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000941 break;
942 }
943 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000944 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000945 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
946 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000947 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000948 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000949 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000950 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000951 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000952 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000953 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
954 * Linux console/xterm; Esc [ 5 ^ ==
955 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000956 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000957 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000958 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
959 * Linux console/xterm; Esc [ 6 ^ ==
960 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000961 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000962 break;
963 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000964 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000965 break;
966 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000967 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000968 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000969 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000970 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000971 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000972 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000973 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000974 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000975 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000976 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000977 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000978 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000979 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000980 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000981 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000982 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000983 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000984 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000985 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000986 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000987 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000988 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000989 case 'E': /* Esc [ E == Center (5) on numeric keypad
990 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000991 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000992 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000993 case 'F': /* Esc [ F == End on FreeBSD
994 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000995 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000996 break;
997 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000998 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000999 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001000 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001001 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001002 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001003 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001004 break;
1005 case 'I': /* Esc [ I == PageUp on FreeBSD
1006 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001007 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001008 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001009 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001010 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001011 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001012 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001013 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001014 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001015 break;
1016 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001017 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001018 break;
1019 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001020 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001021 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001022 case 'P': /* Esc [ O P == F1 on
1023 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001024 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001025 break;
1026 case 'Q': /* Esc [ O Q == F2 on
1027 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001028 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001029 break;
1030 case 'R': /* Esc [ O R == F3 on
1031 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001032 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001033 break;
1034 case 'S': /* Esc [ O S == F4 on
1035 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001036 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001037 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001038 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001039 } else {
1040 /* Esc [ O == F3 on FreeBSD console. */
1041 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001042 }
1043 break;
1044 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001045 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001046 break;
1047 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001048 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001049 break;
1050 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001051 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001052 break;
1053 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001054 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001055 break;
1056 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001057 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001058 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001059 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001060 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001061 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001062 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001063 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001064 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001065 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001066 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001067 break;
1068 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001069 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001070 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001071 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001072 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001073 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001074 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001075 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001076 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001077 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001078 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001079 case 'c': /* Esc [ c == Shift-Right on rxvt/
1080 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001081 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001082 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001083 break;
1084 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001085 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001086 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001087 case 'A': /* Esc [ [ A == F1 on Linux
1088 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001089 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001090 break;
1091 case 'B': /* Esc [ [ B == F2 on Linux
1092 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001093 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001094 break;
1095 case 'C': /* Esc [ [ C == F3 on Linux
1096 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001097 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001098 break;
1099 case 'D': /* Esc [ [ D == F4 on Linux
1100 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001101 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001102 break;
1103 case 'E': /* Esc [ [ E == F5 on Linux
1104 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001105 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001106 break;
1107 }
1108 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001109 break;
1110 }
1111 break;
1112 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001113 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001114
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001115#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001116 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001117#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001118
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001119 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001120}
1121
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001122/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001123 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001124 * to many escape sequences. */
1125int get_escape_seq_abcd(int kbinput)
1126{
1127 switch (tolower(kbinput)) {
1128 case 'a':
1129 return NANO_PREVLINE_KEY;
1130 case 'b':
1131 return NANO_NEXTLINE_KEY;
1132 case 'c':
1133 return NANO_FORWARD_KEY;
1134 case 'd':
1135 return NANO_BACK_KEY;
1136 default:
1137 return ERR;
1138 }
1139}
1140
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001141/* Translate a byte sequence: turn a three-digit decimal number from
1142 * 000 to 255 into its corresponding byte value. */
1143int get_byte_kbinput(int kbinput
1144#ifndef NANO_SMALL
1145 , bool reset
1146#endif
1147 )
1148{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001149 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001150 int retval = ERR;
1151
1152#ifndef NANO_SMALL
1153 if (reset) {
1154 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001155 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001156 return ERR;
1157 }
1158#endif
1159
1160 /* Increment the byte digit counter. */
1161 byte_digits++;
1162
1163 switch (byte_digits) {
1164 case 1:
1165 /* One digit: reset the byte sequence holder and add the
1166 * digit we got to the 100's position of the byte sequence
1167 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001168 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001169 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001170 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001171 else
1172 /* If the character we got isn't a decimal digit, or if
1173 * it is and it would put the byte sequence out of byte
1174 * range, save it as the result. */
1175 retval = kbinput;
1176 break;
1177 case 2:
1178 /* Two digits: add the digit we got to the 10's position of
1179 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001180 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1181 '6' <= kbinput && kbinput <= '9'))
1182 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001183 else
1184 /* If the character we got isn't a decimal digit, or if
1185 * it is and it would put the byte sequence out of byte
1186 * range, save it as the result. */
1187 retval = kbinput;
1188 break;
1189 case 3:
1190 /* Three digits: add the digit we got to the 1's position of
1191 * the byte sequence holder, and save the corresponding word
1192 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001193 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1194 '6' <= kbinput && kbinput <= '9')) {
1195 byte += (kbinput - '0');
1196 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001197 } else
1198 /* If the character we got isn't a decimal digit, or if
1199 * it is and it would put the word sequence out of word
1200 * range, save it as the result. */
1201 retval = kbinput;
1202 break;
1203 default:
1204 /* More than three digits: save the character we got as the
1205 * result. */
1206 retval = kbinput;
1207 break;
1208 }
1209
1210 /* If we have a result, reset the byte digit counter and the byte
1211 * sequence holder. */
1212 if (retval != ERR) {
1213 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001214 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001215 }
1216
1217#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001218 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 +00001219#endif
1220
1221 return retval;
1222}
1223
1224/* Translate a word sequence: turn a four-digit hexadecimal number from
1225 * 0000 to ffff (case-insensitive) into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001226int get_word_kbinput(int kbinput
1227#ifndef NANO_SMALL
1228 , bool reset
1229#endif
1230 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001231{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001232 static int word_digits = 0, word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001233 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001234
1235#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001236 if (reset) {
1237 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001238 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001239 return ERR;
1240 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001241#endif
1242
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001243 /* Increment the word digit counter. */
1244 word_digits++;
1245
1246 switch (word_digits) {
1247 case 1:
1248 /* One digit: reset the word sequence holder and add the
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001249 * digit we got to the 4096's position of the word sequence
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001250 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001251 word = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001252 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001253 word += (kbinput - '0') * 4096;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001254 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001255 word += (tolower(kbinput) + 10 - 'a') * 4096;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001256 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001257 /* If the character we got isn't a hexadecimal digit, or
1258 * if it is and it would put the word sequence out of
1259 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001260 retval = kbinput;
1261 break;
1262 case 2:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001263 /* Two digits: add the digit we got to the 256's position of
1264 * the word sequence holder. */
1265 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001266 word += (kbinput - '0') * 256;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001267 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001268 word += (tolower(kbinput) + 10 - 'a') * 256;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001269 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001270 /* If the character we got isn't a hexadecimal digit, or
1271 * if it is and it would put the word sequence out of
1272 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001273 retval = kbinput;
1274 break;
1275 case 3:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001276 /* Three digits: add the digit we got to the 16's position
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001277 * of the word sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001278 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001279 word += (kbinput - '0') * 16;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001280 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001281 word += (tolower(kbinput) + 10 - 'a') * 16;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001282 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001283 /* If the character we got isn't a hexadecimal digit, or
1284 * if it is and it would put the word sequence out of
1285 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001286 retval = kbinput;
1287 break;
1288 case 4:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001289 /* Four digits: add the digit we got to the 1's position of
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001290 * the word sequence holder, and save the corresponding word
1291 * value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001292 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001293 word += (kbinput - '0');
1294 retval = word;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001295 } else if ('a' <= tolower(kbinput) &&
1296 tolower(kbinput) <= 'f') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001297 word += (tolower(kbinput) + 10 - 'a');
1298 retval = word;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001299 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001300 /* If the character we got isn't a hexadecimal digit, or
1301 * if it is and it would put the word sequence out of
1302 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001303 retval = kbinput;
1304 break;
1305 default:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001306 /* More than four digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001307 * result. */
1308 retval = kbinput;
1309 break;
1310 }
1311
1312 /* If we have a result, reset the word digit counter and the word
1313 * sequence holder. */
1314 if (retval != ERR) {
1315 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001316 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001317 }
1318
1319#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001320 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 +00001321#endif
1322
1323 return retval;
1324}
1325
1326/* Translate a control character sequence: turn an ASCII non-control
1327 * character into its corresponding control character. */
1328int get_control_kbinput(int kbinput)
1329{
1330 int retval;
1331
1332 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1333 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1334 kbinput == '`')
1335 retval = NANO_CONTROL_SPACE;
1336 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1337 else if ('3' <= kbinput && kbinput <= '7')
1338 retval = kbinput - 24;
1339 /* Ctrl-8 (Ctrl-?) */
1340 else if (kbinput == '8' || kbinput == '?')
1341 retval = NANO_CONTROL_8;
1342 /* Ctrl-A to Ctrl-_ */
1343 else if ('A' <= kbinput && kbinput <= '_')
1344 retval = kbinput - 64;
1345 /* Ctrl-a to Ctrl-~ */
1346 else if ('a' <= kbinput && kbinput <= '~')
1347 retval = kbinput - 96;
1348 else
1349 retval = kbinput;
1350
1351#ifdef DEBUG
1352 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1353#endif
1354
1355 return retval;
1356}
1357
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001358/* Put the output-formatted characters in output back into the default
1359 * keystroke buffer, so that they can be parsed and displayed as output
1360 * again. */
1361void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001362{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001363 int *input;
1364 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001365
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001366 if (output_len == 0)
1367 return;
1368
1369 input = (int *)nmalloc(output_len * sizeof(int));
1370 for (i = 0; i < output_len; i++)
1371 input[i] = (int)output[i];
1372 unget_input(input, output_len);
1373 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001374}
1375
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001376/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001377 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1378int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1379{
1380 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001381
1382 /* Turn off flow control characters if necessary so that we can type
1383 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001384 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001385 if (ISSET(PRESERVE))
1386 disable_flow_control();
1387 keypad(win, FALSE);
1388
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001389 /* Read in a stream of characters and interpret it if possible. */
1390 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001391
1392 /* Turn flow control characters back on if necessary and turn the
1393 * keypad back on now that we're done. */
1394 if (ISSET(PRESERVE))
1395 enable_flow_control();
1396 keypad(win, TRUE);
1397
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001398 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001399}
1400
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001401/* Read in a stream of all available characters, and return the length
1402 * of the string in kbinput_len. Translate the first few characters of
1403 * the input into the corresponding word value if possible. After that,
1404 * leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001405int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001406{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001407 int *kbinput, word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001408
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001409 /* Read in the first keystroke. */
1410 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001411
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001412 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001413 word = get_word_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001414#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001415 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001416#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001417 );
1418
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001419 /* If the first keystroke isn't a hexadecimal digit, put back the
1420 * first keystroke. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001421 if (word != ERR)
1422 unget_input(kbinput, 1);
1423 /* Otherwise, read in keystrokes until we have a complete word
1424 * sequence, and put back the corresponding word value. */
1425 else {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00001426 char *word_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001427 int word_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001428
1429 while (word == ERR) {
1430 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001431
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001432 word = get_word_kbinput(*kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001433#ifndef NANO_SMALL
1434 , FALSE
1435#endif
1436 );
1437 }
1438
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001439 /* Put back the multibyte equivalent of the word value. */
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00001440 word_mb = make_mbchar(word, &word_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001441
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001442 seq = (int *)nmalloc(word_mb_len * sizeof(int));
1443
1444 for (i = 0; i < word_mb_len; i++)
1445 seq[i] = (unsigned char)word_mb[i];
1446
1447 unget_input(seq, word_mb_len);
1448
1449 free(seq);
1450 free(word_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001451 }
1452
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001453 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001454 * result. */
1455 *kbinput_len = get_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001456 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001457
1458 return retval;
1459}
1460
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001461#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001462/* Check for a mouse event, and if one's taken place, save the
1463 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001464 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1465 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001466 * place on it, figure out which shortcut was clicked and put back the
1467 * equivalent keystroke(s). Return FALSE if no keystrokes were
1468 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001469 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001470bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001471{
1472 MEVENT mevent;
1473
1474 *mouse_x = -1;
1475 *mouse_y = -1;
1476
1477 /* First, get the actual mouse event. */
1478 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001479 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001480
1481 /* Save the screen coordinates where the mouse event took place. */
1482 *mouse_x = mevent.x;
1483 *mouse_y = mevent.y;
1484
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001485 /* If we're allowing shortcuts, the current shortcut list is being
1486 * displayed on the last two lines of the screen, and the mouse
1487 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001488 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001489 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1490 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001491 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001492 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001493 /* The number of shortcuts in the current shortcut list. */
1494 const shortcut *s = currshortcut;
1495 /* The actual shortcut we clicked on, starting at the first
1496 * one in the current shortcut list. */
1497
1498 /* Get the shortcut lists' length. */
1499 if (currshortcut == main_list)
1500 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001501 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001502 currslen = length_of_list(currshortcut);
1503
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001504 /* We don't show any more shortcuts than the main list
1505 * does. */
1506 if (currslen > MAIN_VISIBLE)
1507 currslen = MAIN_VISIBLE;
1508 }
1509
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001510 /* Calculate the width of each shortcut in the list (it's the
1511 * same for all of them). */
1512 if (currslen < 2)
1513 i = COLS / 6;
1514 else
1515 i = COLS / ((currslen / 2) + (currslen % 2));
1516
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001517 /* Calculate the y-coordinate relative to the beginning of
1518 * bottomwin. */
1519 j = *mouse_y - ((2 - no_more_space()) + 1) - editwinrows;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001520
1521 /* If we're on the statusbar, beyond the end of the shortcut
1522 * list, or beyond the end of a shortcut on the right side of
1523 * the screen, don't do anything. */
1524 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001525 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001526 j = (*mouse_x / i) * 2 + j;
1527 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001528 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001529
1530 /* Go through the shortcut list to determine which shortcut was
1531 * clicked. */
1532 for (; j > 0; j--)
1533 s = s->next;
1534
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001535 /* And put back the equivalent key. Assume that each shortcut
1536 * has, at the very least, an equivalent control key, an
1537 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001538 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001539 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001540 return TRUE;
1541 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001542 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001543 return TRUE;
1544 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001545 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001546 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001547}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001548#endif /* !DISABLE_MOUSE */
1549
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001550const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001551 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001552{
1553 const shortcut *s = s_list;
1554 size_t slen = length_of_list(s_list);
1555
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001556#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001557 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 +00001558#endif
1559
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001560 /* Check for shortcuts. */
1561 for (; slen > 0; slen--) {
1562 /* We've found a shortcut if:
1563 *
1564 * 1. The key exists.
1565 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001566 * 3. meta_key is TRUE and the key is the primary or
1567 * miscellaneous meta sequence in the shortcut list.
1568 * 4. func_key is TRUE and the key is a function key in the
1569 * shortcut list. */
1570
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001571 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1572 (*meta_key == TRUE && (*kbinput == s->metaval ||
1573 *kbinput == s->miscval)) || (*func_key == TRUE &&
1574 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001575 break;
1576 }
1577
1578 s = s->next;
1579 }
1580
1581 /* Translate the shortcut to either its control key or its meta key
1582 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001583 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001584 if (slen > 0) {
1585 if (s->ctrlval != NANO_NO_KEY) {
1586 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001587 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001588 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001589 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001590 } else if (s->metaval != NANO_NO_KEY) {
1591 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001592 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001593 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001594 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001595 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001596 }
1597
1598 return NULL;
1599}
1600
1601#ifndef NANO_SMALL
1602const toggle *get_toggle(int kbinput, bool meta_key)
1603{
1604 const toggle *t = toggles;
1605
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001606#ifdef DEBUG
1607 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1608#endif
1609
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001610 /* Check for toggles. */
1611 for (; t != NULL; t = t->next) {
1612 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001613 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001614 if (meta_key && kbinput == t->val)
1615 break;
1616 }
1617
1618 return t;
1619}
1620#endif /* !NANO_SMALL */
1621
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001622int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001623 bool *ran_func, bool *finished, bool allow_funcs)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001624{
1625 int input;
1626 /* The character we read in. */
1627 static int *kbinput = NULL;
1628 /* The input buffer. */
1629 static size_t kbinput_len = 0;
1630 /* The length of the input buffer. */
1631 const shortcut *s;
1632 bool have_shortcut;
1633
1634 *s_or_t = FALSE;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001635 *ran_func = FALSE;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001636 *finished = FALSE;
1637
1638 /* Read in a character. */
1639 input = get_kbinput(bottomwin, meta_key, func_key);
1640
1641#ifndef DISABLE_MOUSE
1642 /* If we got a mouse click and it was on a shortcut, read in the
1643 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001644 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001645 if (do_mouse())
1646 input = get_kbinput(bottomwin, meta_key, func_key);
1647 else
1648 input = ERR;
1649 }
1650#endif
1651
1652 /* Check for a shortcut in the current list. */
1653 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1654
1655 /* If we got a shortcut from the current list, or a "universal"
1656 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1657 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1658 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1659 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1660 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001661 input == NANO_CUT_KEY ||
1662#ifndef NANO_SMALL
1663 input == NANO_NEXTWORD_KEY ||
1664#endif
1665 (*meta_key == TRUE && (
1666#ifndef NANO_SMALL
1667 input == NANO_PREVWORD_KEY ||
1668#endif
1669 input == NANO_VERBATIM_KEY)));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001670
1671 /* Set s_or_t to TRUE if we got a shortcut. */
1672 *s_or_t = have_shortcut;
1673
1674 if (allow_funcs) {
1675 if (input != ERR && *s_or_t == FALSE && !is_cntrl_char(input)) {
1676 /* If we're using restricted mode, the filename isn't blank,
1677 * and we're at the "Write File" prompt, disable text
1678 * input. */
1679 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1680 currshortcut != writefile_list) {
1681 kbinput_len++;
1682 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1683 sizeof(int));
1684 kbinput[kbinput_len - 1] = input;
1685 }
1686 }
1687
1688 /* If we got a shortcut, or if there aren't any other characters
1689 * waiting after the one we read in, we need to display all the
1690 * characters in the input buffer if it isn't empty. */
1691 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1692 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001693
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001694 /* Display all the characters in the input buffer at
1695 * once. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001696 char *output = charalloc(kbinput_len + 1);
1697 size_t i;
1698 bool got_enter;
1699 /* Whether we got the Enter key. */
1700
1701 for (i = 0; i < kbinput_len; i++)
1702 output[i] = (char)kbinput[i];
1703 output[i] = '\0';
1704
1705 do_statusbar_output(output, kbinput_len, &got_enter);
1706
1707 free(output);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001708
1709 /* Empty the input buffer. */
1710 kbinput_len = 0;
1711 free(kbinput);
1712 kbinput = NULL;
1713 }
1714 }
1715
1716 if (have_shortcut) {
1717 switch (input) {
1718 /* Handle the "universal" statusbar prompt shortcuts. */
1719 case NANO_REFRESH_KEY:
1720 total_refresh();
1721 break;
1722 case NANO_HOME_KEY:
1723 do_statusbar_home();
1724 break;
1725 case NANO_END_KEY:
1726 do_statusbar_end();
1727 break;
1728 case NANO_FORWARD_KEY:
1729 do_statusbar_right();
1730 break;
1731 case NANO_BACK_KEY:
1732 do_statusbar_left();
1733 break;
1734 case NANO_BACKSPACE_KEY:
1735 /* If we're using restricted mode, the filename
1736 * isn't blank, and we're at the "Write File"
1737 * prompt, disable Backspace. */
1738 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1739 currshortcut != writefile_list)
1740 do_statusbar_backspace();
1741 break;
1742 case NANO_DELETE_KEY:
1743 /* If we're using restricted mode, the filename
1744 * isn't blank, and we're at the "Write File"
1745 * prompt, disable Delete. */
1746 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1747 currshortcut != writefile_list)
1748 do_statusbar_delete();
1749 break;
1750 case NANO_CUT_KEY:
1751 /* If we're using restricted mode, the filename
1752 * isn't blank, and we're at the "Write File"
1753 * prompt, disable Cut. */
1754 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1755 currshortcut != writefile_list)
1756 do_statusbar_cut_text();
1757 break;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001758#ifndef NANO_SMALL
1759 case NANO_NEXTWORD_KEY:
1760 do_statusbar_next_word();
1761 break;
1762 case NANO_PREVWORD_KEY:
1763 if (*meta_key == TRUE)
1764 do_statusbar_prev_word();
1765 break;
1766#endif
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001767 case NANO_VERBATIM_KEY:
1768 if (*meta_key == TRUE) {
1769 /* If we're using restricted mode, the filename
1770 * isn't blank, and we're at the "Write File"
1771 * prompt, disable verbatim input. */
1772 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001773 currshortcut != writefile_list) {
1774 bool got_enter;
1775 /* Whether we got the Enter key. */
1776
1777 do_statusbar_verbatim_input(&got_enter);
1778
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001779 /* If we got the Enter key, set input to the
1780 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001781 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001782 if (got_enter) {
1783 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001784 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001785 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001786 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001787 break;
1788 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001789 /* Handle the normal statusbar prompt shortcuts, setting
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001790 * ran_func to TRUE if we try to run their associated
1791 * functions and setting finished to TRUE to indicate
1792 * that we're done after trying to run their associated
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001793 * functions. */
1794 default:
1795 if (s->func != NULL) {
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001796 *ran_func = TRUE;
1797 if (!ISSET(VIEW_MODE) || s->viewok)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001798 s->func();
1799 }
1800 *finished = TRUE;
1801 }
1802 }
1803 }
1804
1805 return input;
1806}
1807
1808#ifndef DISABLE_MOUSE
1809bool do_statusbar_mouse(void)
1810{
1811 /* FIXME: If we clicked on a location in the statusbar, the cursor
1812 * should move to the location we clicked on. This functionality
1813 * should be in this function. */
1814 int mouse_x, mouse_y;
1815 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1816}
1817#endif
1818
1819void do_statusbar_home(void)
1820{
1821#ifndef NANO_SMALL
1822 if (ISSET(SMART_HOME)) {
1823 size_t statusbar_x_save = statusbar_x;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001824
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001825 statusbar_x = indent_length(answer);
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001826
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001827 if (statusbar_x == statusbar_x_save ||
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001828 statusbar_x == strlen(answer))
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001829 statusbar_x = 0;
1830 } else
1831#endif
1832 statusbar_x = 0;
1833}
1834
1835void do_statusbar_end(void)
1836{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001837 statusbar_x = strlen(answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001838}
1839
1840void do_statusbar_right(void)
1841{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001842 if (statusbar_x < strlen(answer))
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001843 statusbar_x = move_mbright(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001844}
1845
1846void do_statusbar_left(void)
1847{
1848 if (statusbar_x > 0)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001849 statusbar_x = move_mbleft(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001850}
1851
1852void do_statusbar_backspace(void)
1853{
1854 if (statusbar_x > 0) {
1855 do_statusbar_left();
1856 do_statusbar_delete();
1857 }
1858}
1859
1860void do_statusbar_delete(void)
1861{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001862 if (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001863 int char_buf_len = parse_mbchar(answer + statusbar_x, NULL,
1864 NULL, NULL);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001865 size_t line_len = strlen(answer + statusbar_x);
1866
1867 assert(statusbar_x < strlen(answer));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001868
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001869 charmove(answer + statusbar_x, answer + statusbar_x +
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001870 char_buf_len, strlen(answer) - statusbar_x -
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001871 char_buf_len + 1);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001872
1873 null_at(&answer, statusbar_x + line_len - char_buf_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001874 }
1875}
1876
1877void do_statusbar_cut_text(void)
1878{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001879 assert(answer != NULL);
1880
1881 if (ISSET(CUT_TO_END))
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001882 null_at(&answer, statusbar_x);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001883 else {
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001884 null_at(&answer, 0);
1885 statusbar_x = 0;
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001886 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001887}
1888
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001889#ifndef NANO_SMALL
1890void do_statusbar_next_word(void)
1891{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001892 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001893 int char_mb_len;
1894
1895 assert(answer != NULL);
1896
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001897 char_mb = charalloc(mb_cur_max());
1898
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001899 /* Move forward until we find the character after the last letter of
1900 * the current word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001901 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001902 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1903 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001904
1905 /* If we've found it, stop moving forward through the current
1906 * line. */
1907 if (!is_alnum_mbchar(char_mb))
1908 break;
1909
1910 statusbar_x += char_mb_len;
1911 }
1912
1913 /* Move forward until we find the first letter of the next word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001914 if (answer[statusbar_x] != '\0')
1915 statusbar_x += char_mb_len;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001916
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001917 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001918 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1919 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001920
1921 /* If we've found it, stop moving forward through the current
1922 * line. */
1923 if (is_alnum_mbchar(char_mb))
1924 break;
1925
1926 statusbar_x += char_mb_len;
1927 }
1928
1929 free(char_mb);
1930}
1931
1932void do_statusbar_prev_word(void)
1933{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001934 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001935 int char_mb_len;
1936 bool begin_line = FALSE;
1937
1938 assert(answer != NULL);
1939
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001940 char_mb = charalloc(mb_cur_max());
1941
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001942 /* Move backward until we find the character before the first letter
1943 * of the current word. */
1944 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001945 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1946 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001947
1948 /* If we've found it, stop moving backward through the current
1949 * line. */
1950 if (!is_alnum_mbchar(char_mb))
1951 break;
1952
1953 if (statusbar_x == 0)
1954 begin_line = TRUE;
1955 else
1956 statusbar_x = move_mbleft(answer, statusbar_x);
1957 }
1958
1959 /* Move backward until we find the last letter of the previous
1960 * word. */
1961 if (statusbar_x == 0)
1962 begin_line = TRUE;
1963 else
1964 statusbar_x = move_mbleft(answer, statusbar_x);
1965
1966 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001967 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1968 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001969
1970 /* If we've found it, stop moving backward through the current
1971 * line. */
1972 if (is_alnum_mbchar(char_mb))
1973 break;
1974
1975 if (statusbar_x == 0)
1976 begin_line = TRUE;
1977 else
1978 statusbar_x = move_mbleft(answer, statusbar_x);
1979 }
1980
1981 /* If we've found it, move backward until we find the character
1982 * before the first letter of the previous word. */
1983 if (!begin_line) {
1984 if (statusbar_x == 0)
1985 begin_line = TRUE;
1986 else
1987 statusbar_x = move_mbleft(answer, statusbar_x);
1988
1989 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001990 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
1991 NULL, NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001992
1993 /* If we've found it, stop moving backward through the
1994 * current line. */
1995 if (!is_alnum_mbchar(char_mb))
1996 break;
1997
1998 if (statusbar_x == 0)
1999 begin_line = TRUE;
2000 else
2001 statusbar_x = move_mbleft(answer, statusbar_x);
2002 }
2003
2004 /* If we've found it, move forward to the first letter of the
2005 * previous word. */
2006 if (!begin_line)
2007 statusbar_x += char_mb_len;
2008 }
2009
2010 free(char_mb);
2011}
2012#endif
2013
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002014void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002015{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002016 int *kbinput;
2017 size_t kbinput_len, i;
2018 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002019
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002020 *got_enter = FALSE;
2021
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002022 /* Read in all the verbatim characters. */
2023 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
2024
2025 /* Display all the verbatim characters at once. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002026 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002027
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002028 for (i = 0; i < kbinput_len; i++)
2029 output[i] = (char)kbinput[i];
2030 output[i] = '\0';
2031
2032 do_statusbar_output(output, kbinput_len, got_enter);
2033
2034 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002035}
2036
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002037void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002038 *got_enter)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002039{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002040 size_t answer_len = strlen(answer), i = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002041 char *char_buf = charalloc(mb_cur_max());
2042 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002043
2044 assert(answer != NULL);
2045
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002046 *got_enter = FALSE;
2047
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002048 while (i < output_len) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002049 /* Null to newline, if needed. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002050 if (output[i] == '\0')
2051 output[i] = '\n';
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002052 /* Newline to Enter, if needed. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002053 else if (output[i] == '\n') {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002054 /* Set got_enter to TRUE to indicate that we got the Enter
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002055 * key, put back the rest of the characters in output so
2056 * that they can be parsed and output again, and get out. */
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002057 *got_enter = TRUE;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002058 unparse_kbinput(output + i, output_len - i);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002059 return;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002060 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002061
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002062 /* Interpret the next multibyte character. If it's an invalid
2063 * multibyte character, interpret it as though it's a byte
2064 * character. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002065 char_buf_len = parse_mbchar(output + i, char_buf, NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002066
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002067 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002068
2069 /* More dangerousness fun =) */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002070 answer = charealloc(answer, answer_len + (char_buf_len * 2));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002071
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002072 assert(statusbar_x <= answer_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002073
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002074 charmove(&answer[statusbar_x + char_buf_len],
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002075 &answer[statusbar_x], answer_len - statusbar_x +
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002076 char_buf_len);
2077 charcpy(&answer[statusbar_x], char_buf, char_buf_len);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002078 answer_len += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002079
2080 do_statusbar_right();
2081 }
2082
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002083 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002084}
2085
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002086/* Return the placewewant associated with current_x, i.e, the zero-based
2087 * column position of the cursor. The value will be no smaller than
2088 * current_x. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002089size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002090{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002091 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002092}
2093
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002094/* actual_x() gives the index in str of the character displayed at
2095 * column xplus. That is, actual_x() is the largest value such that
2096 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2097size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002098{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002099 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002100 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002101 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002102 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002103
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002104 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002105
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002106 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002107 int str_len = parse_mbchar(str, NULL, NULL, &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002108
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002109 if (length > xplus)
2110 break;
2111
2112 i += str_len;
2113 str += str_len;
2114 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002115
Chris Allegretta6df90f52002-07-19 01:08:59 +00002116 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002117}
2118
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002119/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002120 * columns wide are the first size characters of str? */
2121size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002122{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002123 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002124 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002125
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002126 if (size == 0)
2127 return 0;
2128
2129 assert(str != NULL);
2130
2131 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002132 int str_len = parse_mbchar(str, NULL, NULL, &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002133
2134 str += str_len;
2135
2136 if (size <= str_len)
2137 break;
2138
2139 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002140 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002141
Chris Allegretta6df90f52002-07-19 01:08:59 +00002142 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002143}
2144
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002145/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002146size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002147{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002148 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002149}
2150
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002151void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002152{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002153 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002154}
2155
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002156void blank_topbar(void)
2157{
2158 if (!ISSET(MORE_SPACE))
2159 mvwaddstr(topwin, 1, 0, hblank);
2160}
2161
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002162void blank_edit(void)
2163{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002164 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002165 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002166 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002167}
2168
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002169void blank_statusbar(void)
2170{
2171 mvwaddstr(bottomwin, 0, 0, hblank);
2172}
2173
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002174void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002175{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002176 if (statusblank > 1)
2177 statusblank--;
2178 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
2179 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002180 blank_statusbar();
2181 wnoutrefresh(bottomwin);
2182 reset_cursor();
2183 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002184 }
2185}
2186
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002187void blank_bottombars(void)
2188{
2189 if (!ISSET(NO_HELP)) {
2190 mvwaddstr(bottomwin, 1, 0, hblank);
2191 mvwaddstr(bottomwin, 2, 0, hblank);
2192 }
2193}
2194
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002195/* Convert buf into a string that can be displayed on screen. The
2196 * caller wants to display buf starting with column start_col, and
2197 * extending for at most len columns. start_col is zero-based. len is
2198 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002199 * string is dynamically allocated, and should be freed. If dollars is
2200 * TRUE, the caller might put "$" at the beginning or end of the line if
2201 * it's too long. */
2202char *display_string(const char *buf, size_t start_col, size_t len, bool
2203 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002204{
2205 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002206 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002207 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002208 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002209 size_t alloc_len;
2210 /* The length of memory allocated for converted. */
2211 char *converted;
2212 /* The string we return. */
2213 size_t index;
2214 /* Current position in converted. */
2215
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002216 char *buf_mb = charalloc(mb_cur_max());
2217 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002218 bool bad_char;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002219
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002220 /* If dollars is TRUE, make room for the "$" at the end of the
2221 * line. */
2222 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2223 len--;
2224
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002225 if (len == 0)
2226 return mallocstrcpy(NULL, "");
2227
2228 start_index = actual_x(buf, start_col);
2229 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002230
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002231 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002232
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002233 /* Allocate enough space for the entire line. It should contain
2234 * (len + 2) multibyte characters at most. */
2235 alloc_len = mb_cur_max() * (len + 2);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002236
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002237 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002238 index = 0;
2239
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002240 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002241 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002242 /* We don't display all of buf[start_index] since it starts to
2243 * the left of the screen. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002244 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL,
2245 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002246
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002247 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002248 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002249 char *ctrl_buf_mb = charalloc(mb_cur_max());
2250 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002251
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002252 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2253 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002254
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002255 for (i = 0; i < ctrl_buf_mb_len; i++)
2256 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002257
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002258 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002259
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002260 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002261
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002262 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002263 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002264 }
2265#ifdef NANO_WIDE
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002266 else if (mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002267 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002268 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002269
2270 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002271 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002272#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002273 }
2274
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002275 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseybc149412005-02-11 20:23:00 +00002276 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, &bad_char,
2277 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002278
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002279 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002280#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002281 if (ISSET(WHITESPACE_DISPLAY)) {
2282 int i;
2283
2284 for (i = 0; i < whitespace_len[0]; i++)
2285 converted[index++] = whitespace[i];
2286 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002287#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002288 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002289 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002290 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002291 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002292 start_col++;
2293 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002294 /* If buf contains a control character, interpret it. If it
2295 * contains an invalid multibyte control character, interpret
2296 * that character as though it's a normal control character. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002297 } else if (is_cntrl_mbchar(buf_mb)) {
2298 char *ctrl_buf_mb = charalloc(mb_cur_max());
2299 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002300
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002301 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002302 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002303
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002304 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2305 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002306
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002307 for (i = 0; i < ctrl_buf_mb_len; i++)
2308 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002309
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002310 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002311
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002312 free(ctrl_buf_mb);
2313 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002314#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002315 if (ISSET(WHITESPACE_DISPLAY)) {
2316 int i;
2317
2318 for (i = whitespace_len[0]; i < whitespace_len[0] +
2319 whitespace_len[1]; i++)
2320 converted[index++] = whitespace[i];
2321 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002322#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002323 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002324 start_col++;
2325 } else {
2326 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002327
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002328#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002329 /* If buf contains an invalid multibyte non-control
2330 * character, interpret that character as though it's a
2331 * normal non-control character. */
2332 if (!ISSET(NO_UTF8) && bad_char) {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002333 char *bad_buf_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002334 int bad_buf_mb_len;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002335
David Lawrence Ramsey4c6956b2005-01-12 04:32:43 +00002336 bad_buf_mb = make_mbchar((unsigned char)*buf_mb,
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002337 &bad_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002338
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002339 for (i = 0; i < bad_buf_mb_len; i++)
2340 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002341
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002342 start_col += mbwidth(bad_buf_mb);
2343
2344 free(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002345 } else {
2346#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002347 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002348 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002349
2350 start_col += mbwidth(buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002351#ifdef NANO_WIDE
2352 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002353#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002354 }
2355
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002356 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002357 }
2358
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002359 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002360 converted[index] = '\0';
2361
2362 /* Make sure converted takes up no more than len columns. */
2363 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002364 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002365
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002366 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002367}
2368
Chris Allegretta7662c862003-01-13 01:35:15 +00002369/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002370 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002371 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002372 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002373 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002374void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002375{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002376 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002377 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002378
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002379 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002380
Chris Allegrettab3655b42001-10-22 03:15:31 +00002381 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002382 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002383
Chris Allegretta6df90f52002-07-19 01:08:59 +00002384 mvwaddstr(bottomwin, 0, 0, buf);
2385 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002386
2387 if (COLS > 1)
2388 waddch(bottomwin, x_real < wid ? ' ' : '$');
2389 if (COLS > 2) {
2390 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002391 char *expanded = display_string(inputbuf, page_start, wid,
2392 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002393
2394 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002395 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002396
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002397 waddstr(bottomwin, expanded);
2398 free(expanded);
2399 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2400 } else
2401 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002402 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002403}
2404
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002405/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002406 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002407int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002408#ifndef NANO_SMALL
2409 historyheadtype *history_list,
2410#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002411 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002412#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002413 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002414#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002415 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002416{
2417 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002418 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002419 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002420 /* used by input_tab() */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002421 size_t answer_len = strlen(def);
Chris Allegretta598106e2002-01-19 01:59:37 +00002422
Chris Allegretta5beed502003-01-05 20:41:21 +00002423#ifndef NANO_SMALL
2424 /* for history */
2425 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00002426 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00002427 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002428 int last_kbinput = 0;
2429
2430 /* This variable is used in the search history code. use_cb == 0
2431 means that we're using the existing history and ignoring
2432 currentbuf. use_cb == 1 means that the entry in answer should be
2433 moved to currentbuf or restored from currentbuf to answer.
2434 use_cb == 2 means that the entry in currentbuf should be moved to
2435 answer or restored from answer to currentbuf. */
2436 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002437#endif
Chris Allegretta09fc4302003-01-16 22:16:38 +00002438
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002439 /* Only put statusbar_x at the end of the string if it's
2440 * uninitialized, if it would be past the end of the string as it
2441 * is, or if resetstatuspos is TRUE. Otherwise, leave it alone.
2442 * This is so the cursor position stays at the same place if a
2443 * prompt-changing toggle is pressed. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002444 if (statusbar_x == (size_t)-1 || statusbar_x > answer_len ||
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002445 resetstatuspos)
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002446 statusbar_x = answer_len;
Chris Allegretta09fc4302003-01-16 22:16:38 +00002447
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002448 answer = charealloc(answer, answer_len + 1);
2449 if (answer_len > 0)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002450 strcpy(answer, def);
2451 else
2452 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002453
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002454 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002455
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002456 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00002457
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002458 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002459
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002460 /* Refresh the edit window before getting input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002461 wnoutrefresh(edit);
2462 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002463
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002464 /* If we're using restricted mode, we aren't allowed to change the
2465 * name of a file once it has one because that would allow writing
2466 * to files not specified on the command line. In this case,
2467 * disable all keys that would change the text if the filename isn't
2468 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002469 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002470 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002471 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002472
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002473 /* If we have a shortcut with an associated function, break out
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002474 * if we're finished after running or trying to run the
2475 * function. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002476 if (finished)
2477 break;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002478
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002479 assert(statusbar_x <= answer_len && answer_len == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002480
Chris Allegretta04d848e2000-11-05 17:54:41 +00002481 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002482 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00002483
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002484 switch (kbinput) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002485 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002486#ifndef NANO_SMALL
2487 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00002488 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002489 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002490 history_list->current = (historytype *)history_list;
2491 history_list->len = strlen(answer);
2492 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002493
Chris Allegretta7662c862003-01-13 01:35:15 +00002494 if (history_list->len > 0) {
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002495 complete = get_history_completion(history_list,
2496 answer);
Chris Allegretta5beed502003-01-05 20:41:21 +00002497 answer = mallocstrcpy(answer, complete);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002498 answer_len = strlen(answer);
2499 statusbar_x = answer_len;
Chris Allegretta5beed502003-01-05 20:41:21 +00002500 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002501 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002502#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002503 else
2504#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002505#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002506#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002507 if (allow_tabs) {
David Lawrence Ramsey65e6ecb2005-02-08 20:37:53 +00002508 answer = input_tab(answer, &statusbar_x, &tabbed, list);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002509 answer_len = strlen(answer);
Chris Allegretta5beed502003-01-05 20:41:21 +00002510 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002511 break;
David Lawrence Ramsey65e6ecb2005-02-08 20:37:53 +00002512#endif
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002513 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002514#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002515 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002516
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002517 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2518 isn't NULL, and currentbuf is different from answer,
2519 it means that we're scrolling up at the top of the
2520 search history, and we need to save the current
2521 answer in currentbuf; do this and reset use_cb to
2522 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002523 if (currentbuf == NULL || (use_cb == 1 &&
2524 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002525 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002526 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002527 }
2528
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002529 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2530 is different from answer, it means that we're
2531 scrolling up at the bottom of the search history, and
2532 we need to make the string in currentbuf the current
2533 answer; do this, blow away currentbuf since we don't
2534 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002535 if (currentbuf != NULL && use_cb == 2 &&
2536 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002537 answer = mallocstrcpy(answer, currentbuf);
2538 free(currentbuf);
2539 currentbuf = NULL;
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002540 answer_len = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002541 use_cb = 0;
2542
2543 /* else get older search from the history list and save
2544 it in answer; if there is no older search, blank out
2545 answer */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002546 } else if ((history =
2547 get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002548 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002549 answer_len = strlen(history);
Chris Allegretta5beed502003-01-05 20:41:21 +00002550 } else {
2551 answer = mallocstrcpy(answer, "");
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002552 answer_len = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002553 }
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002554 statusbar_x = answer_len;
Chris Allegretta5beed502003-01-05 20:41:21 +00002555 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002556#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002557 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002558 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002559#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002560 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002561
2562 /* get newer search from the history list and save it
2563 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002564 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002565 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002566 answer_len = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002567
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002568 /* if there is no newer search, we're here */
2569
2570 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2571 that we're scrolling down at the bottom of the search
2572 history and we need to make the string in currentbuf
2573 the current answer; do this, blow away currentbuf
2574 since we don't need it anymore, and set use_cb to
2575 1 */
2576 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002577 answer = mallocstrcpy(answer, currentbuf);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002578 answer_len = strlen(answer);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002579 free(currentbuf);
2580 currentbuf = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002581 use_cb = 1;
2582
2583 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2584 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002585 the search history and the current answer (if it's
2586 not blank) needs to be saved in currentbuf; do this,
2587 blank out answer (if necessary), and set use_cb to
2588 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002589 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002590 if (answer[0] != '\0') {
2591 currentbuf = mallocstrcpy(currentbuf, answer);
2592 answer = mallocstrcpy(answer, "");
2593 }
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002594 answer_len = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002595 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002596 }
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002597 statusbar_x = answer_len;
Chris Allegretta5beed502003-01-05 20:41:21 +00002598 }
2599#endif
2600 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002601 }
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002602#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002603 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002604#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002605 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002606 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002607 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002608
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002609 /* We finished putting in an answer or ran a normal shortcut's
2610 * associated function, so reset statusbar_x. */
2611 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
2612 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002613 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002614
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002615 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002616}
2617
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002618/* Ask a question on the statusbar. Answer will be stored in answer
2619 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2620 * otherwise, the valid shortcut key caught. def is any editable text
2621 * we want to put up by default.
2622 *
2623 * New arg tabs tells whether or not to allow tab completion. */
2624int statusq(bool allow_tabs, const shortcut *s, const char *def,
2625#ifndef NANO_SMALL
2626 historyheadtype *which_history,
2627#endif
2628 const char *msg, ...)
2629{
2630 va_list ap;
2631 char *foo = charalloc(COLS - 3);
2632 int ret;
2633#ifndef DISABLE_TABCOMP
2634 bool list = FALSE;
2635#endif
2636
2637 bottombars(s);
2638
2639 va_start(ap, msg);
2640 vsnprintf(foo, COLS - 4, msg, ap);
2641 va_end(ap);
2642 foo[COLS - 4] = '\0';
2643
2644 ret = nanogetstr(allow_tabs, foo, def,
2645#ifndef NANO_SMALL
2646 which_history,
2647#endif
2648 s
2649#ifndef DISABLE_TABCOMP
2650 , &list
2651#endif
2652 );
2653 free(foo);
2654 resetstatuspos = FALSE;
2655
2656 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002657 case NANO_CANCEL_KEY:
2658 ret = -1;
2659 resetstatuspos = TRUE;
2660 break;
2661 case NANO_ENTER_KEY:
2662 ret = (answer[0] == '\0') ? -2 : 0;
2663 resetstatuspos = TRUE;
2664 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002665 }
2666 blank_statusbar();
2667
2668#ifdef DEBUG
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002669 fprintf(stderr, "answer = \"%s\"\n", answer);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002670#endif
2671
2672#ifndef DISABLE_TABCOMP
2673 /* if we've done tab completion, there might be a list of
2674 filename matches on the edit window at this point; make sure
2675 they're cleared off. */
2676 if (list)
2677 edit_refresh();
2678#endif
2679
2680 return ret;
2681}
2682
2683void statusq_abort(void)
2684{
2685 resetstatuspos = TRUE;
2686}
2687
Chris Allegrettaf717f982003-02-13 22:25:01 +00002688void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002689{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002690 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002691 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002692 size_t verlen = strlenpt(VERMSG) + 1;
2693 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002694 const char *prefix;
2695 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2696 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002697 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002698 const char *state;
2699 /* "Modified", "View", or spaces the length of "Modified".
2700 * Tells the state of this buffer. */
2701 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002702 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002703 char *exppath = NULL;
2704 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002705 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002706 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002707 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002708 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002709
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002710 assert(path != NULL || filename != NULL);
2711 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002712
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002713 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002714
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002715 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002716
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002717 if (COLS <= 5 || COLS - 5 < verlen)
2718 space = 0;
2719 else {
2720 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002721 /* Reserve 2/3 of the screen plus one column for after the
2722 * version message. */
2723 if (space < COLS - (COLS / 3) + 1)
2724 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002725 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002726
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002727 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002728 /* The version message should only take up 1/3 of the screen
2729 * minus one column. */
2730 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002731 waddstr(topwin, " ");
2732 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002733
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002734 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002735 state = _("Modified");
2736 else if (path == NULL && ISSET(VIEW_MODE))
2737 state = _("View");
2738 else {
2739 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002740 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002741 state = &hblank[COLS - statelen];
2742 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002743 statelen = strnlenpt(state, COLS);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002744 /* We need a space before state. */
2745 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2746 statelen++;
2747
2748 assert(space >= 0);
2749 if (space == 0 || statelen >= space)
2750 goto the_end;
2751
2752#ifndef DISABLE_BROWSER
2753 if (path != NULL)
2754 prefix = _("DIR:");
2755 else
2756#endif
2757 if (filename[0] == '\0') {
2758 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002759 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002760 } else
2761 prefix = _("File:");
2762 assert(statelen < space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002763 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002764 /* If newfie is FALSE, we need a space after prefix. */
2765 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002766 prefixlen++;
2767
2768 if (path == NULL)
2769 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002770 if (space >= prefixlen + statelen)
2771 space -= prefixlen + statelen;
2772 else
2773 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002774 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002775 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002776 size_t lenpt = strlenpt(path), start_col;
2777
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002778 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002779
2780 if (dots) {
2781 start_col = lenpt - space + 3;
2782 space -= 3;
2783 } else
2784 start_col = 0;
2785
2786 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002787 }
2788
2789 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002790 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2791 /* The length of the expanded filename. */
2792
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002793 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002794 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002795 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002796 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002797 assert(strlenpt(prefix) + 1 == prefixlen);
2798
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002799 waddch(topwin, ' ');
2800 waddstr(topwin, exppath);
2801 }
2802 } else {
2803 /* We will say something like "File: ...ename". */
2804 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002805 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002806 goto the_end;
2807 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002808 waddnstr(topwin, "...", space + 3);
2809 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002810 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002811 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002812 }
2813
2814 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002815 free(exppath);
2816
2817 if (COLS <= 1 || statelen >= COLS - 1)
2818 mvwaddnstr(topwin, 0, 0, state, COLS);
2819 else {
2820 assert(COLS - statelen - 2 >= 0);
2821 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2822 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2823 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002824
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002825 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002826
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002827 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002828 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002829 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002830}
2831
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002832/* If modified is not already set, set it and update titlebar. */
2833void set_modified(void)
2834{
2835 if (!ISSET(MODIFIED)) {
2836 SET(MODIFIED);
2837 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002838 }
2839}
2840
2841void statusbar(const char *msg, ...)
2842{
2843 va_list ap;
2844
2845 va_start(ap, msg);
2846
2847 /* Curses mode is turned off. If we use wmove() now, it will muck
2848 * up the terminal settings. So we just use vfprintf(). */
2849 if (curses_ended) {
2850 vfprintf(stderr, msg, ap);
2851 va_end(ap);
2852 return;
2853 }
2854
2855 /* Blank out the line. */
2856 blank_statusbar();
2857
2858 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002859 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002860 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002861#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002862 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002863
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002864 UNSET(WHITESPACE_DISPLAY);
2865#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002866 bar = charalloc(mb_cur_max() * (COLS - 3));
2867 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002868 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002869 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002870#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2871 if (old_whitespace)
2872 SET(WHITESPACE_DISPLAY);
2873#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002874 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002875 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002876 start_x = (COLS - foo_len - 4) / 2;
2877
2878 wmove(bottomwin, 0, start_x);
2879 wattron(bottomwin, A_REVERSE);
2880
2881 waddstr(bottomwin, "[ ");
2882 waddstr(bottomwin, foo);
2883 free(foo);
2884 waddstr(bottomwin, " ]");
2885 wattroff(bottomwin, A_REVERSE);
2886 wnoutrefresh(bottomwin);
2887 reset_cursor();
2888 wrefresh(edit);
2889 /* Leave the cursor at its position in the edit window, not
2890 * in the statusbar. */
2891 }
2892
2893 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002894 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002895}
2896
Chris Allegretta6232d662002-05-12 19:52:15 +00002897void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002898{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002899 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002900
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002901 if (ISSET(NO_HELP))
2902 return;
2903
Chris Allegretta6232d662002-05-12 19:52:15 +00002904 if (s == main_list) {
2905 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002906 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002907 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002908 slen = length_of_list(s);
2909
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002910 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002911 if (slen > MAIN_VISIBLE)
2912 slen = MAIN_VISIBLE;
2913 }
2914
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002915 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002916 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002917 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002918
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002919 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002920
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002921 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002922 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002923
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002924 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002925#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002926 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002927 keystr = _("Up");
2928 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002929#endif
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00002930 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002931
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002932 if (s->ctrlval == NANO_CONTROL_SPACE)
2933 strcpy(foo, "^ ");
2934 else if (s->ctrlval == NANO_CONTROL_8)
2935 strcpy(foo, "^?");
2936 /* Normal values. Assume that the shortcut has an
2937 * equivalent control key, meta key sequence, or both. */
2938 else if (s->ctrlval != NANO_NO_KEY)
2939 sprintf(foo, "^%c", s->ctrlval + 64);
2940 else if (s->metaval != NANO_NO_KEY)
2941 sprintf(foo, "M-%c", toupper(s->metaval));
2942
2943 keystr = foo;
2944#ifndef NANO_SMALL
2945 }
2946#endif
2947
2948 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002949 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002950 }
2951
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002952 wnoutrefresh(bottomwin);
2953 reset_cursor();
2954 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002955}
2956
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002957/* Write a shortcut key to the help area at the bottom of the window.
2958 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2959 * to write at most len characters, even if len is very small and
2960 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2961 * the whole string! We do not bother padding the entry with blanks. */
2962void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002963{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002964 size_t keystroke_len = strlenpt(keystroke) + 1;
2965
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002966 assert(keystroke != NULL && desc != NULL);
2967
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002968 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002969 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002970 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002971
2972 if (len > keystroke_len)
2973 len -= keystroke_len;
2974 else
2975 len = 0;
2976
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002977 if (len > 0) {
2978 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002979 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002980 }
2981}
2982
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002983/* And so start the display update routines. */
2984
2985#ifndef NDEBUG
2986int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002987{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002988 int check_line = 0;
2989 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002990
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002991 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
2992 check_line++;
2993 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002994}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002995#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00002996
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002997/* nano scrolls horizontally within a line in chunks. This function
2998 * returns the column number of the first character displayed in the
2999 * window when the cursor is at the given column. Note that
3000 * 0 <= column - get_page_start(column) < COLS. */
3001size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00003002{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003003 assert(COLS > 0);
3004 if (column == 0 || column < COLS - 1)
3005 return 0;
3006 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00003007 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003008 else if (COLS > 2)
3009 return column - (COLS - 2);
3010 else
3011 return column - (COLS - 1);
3012 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003013}
3014
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003015/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003016 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003017void reset_cursor(void)
3018{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003019 /* If we haven't opened any files yet, put the cursor in the top
3020 * left corner of the edit window and get out. */
3021 if (edittop == NULL || current == NULL) {
3022 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003023 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003024 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003025
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003026 current_y = current->lineno - edittop->lineno;
3027 if (current_y < editwinrows) {
3028 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003029 wmove(edit, current_y, x - get_page_start(x));
3030 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003031}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003032
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003033/* edit_add() takes care of the job of actually painting a line into the
3034 * edit window. fileptr is the line to be painted, at row yval of the
3035 * window. converted is the actual string to be written to the window,
3036 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003037 * characters. start is the column number of the first character of
3038 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003039 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003040void edit_add(const filestruct *fileptr, const char *converted, int
3041 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003042{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003043#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003044 size_t startpos = actual_x(fileptr->data, start);
3045 /* The position in fileptr->data of the leftmost character
3046 * that displays at least partially on the window. */
3047 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3048 /* The position in fileptr->data of the first character that is
3049 * completely off the window to the right.
3050 *
3051 * Note that endpos might be beyond the null terminator of the
3052 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003053#endif
3054
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003055 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003056 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003057
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003058 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003059 * just the text that needs it). */
3060 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003061
Chris Allegretta7dd77682001-12-08 19:52:28 +00003062#ifdef ENABLE_COLOR
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003063 if (colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003064 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003065
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003066 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3067 int x_start;
3068 /* Starting column for mvwaddnstr. Zero-based. */
3069 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003070 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003071 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003072 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003073 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003074 regmatch_t startmatch; /* match position for start_regexp */
3075 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003076
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003077 if (tmpcolor->bright)
3078 wattron(edit, A_BOLD);
3079 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003080 /* Two notes about regexec(). Return value 0 means there is
3081 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003082 * after the match. */
3083
3084 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003085 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003086 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003087
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003088 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003089 * last match. Even though two matches may overlap, we
3090 * want to ignore them, so that we can highlight
3091 * C-strings correctly. */
3092 while (k < endpos) {
3093 /* Note the fifth parameter to regexec(). It says
3094 * not to match the beginning-of-line character
3095 * unless k is 0. If regexec() returns REG_NOMATCH,
3096 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003097 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003098 &startmatch, (k == 0) ? 0 :
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003099 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003100 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003101 /* Translate the match to the beginning of the
3102 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003103 startmatch.rm_so += k;
3104 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003105 if (startmatch.rm_so == startmatch.rm_eo) {
3106 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003107 statusbar(
3108 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003109 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003110 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003111 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003112 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003113 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003114 x_start = strnlenpt(fileptr->data,
3115 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003116
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003117 index = actual_x(converted, x_start);
3118
3119 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003120 strnlenpt(fileptr->data,
3121 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003122
3123 assert(0 <= x_start && 0 <= paintlen);
3124
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003125 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003126 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003127 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003128 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003129 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003130 } else {
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003131 /* This is a multi-line regexp. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003132 * First, we have to see if the beginning of the line is
3133 * colored by a start on an earlier line, and an end on
3134 * this line or later.
3135 *
3136 * We find the first line before fileptr matching the
3137 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003138 * end, then go to step two. Otherwise, find the next
3139 * line after start_line matching the end. If that line
3140 * is not before fileptr, then paint the beginning of
3141 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003142 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003143 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003144 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003145 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003146 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003147
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003148 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003149 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003150 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003151 /* If there is an end on this line, there is no need
3152 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003153 if (regexec(tmpcolor->end, start_line->data, 0,
3154 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003155 goto step_two;
3156 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003157 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003158 /* No start found, so skip to the next step. */
3159 if (start_line == NULL)
3160 goto step_two;
3161 /* Now start_line is the first line before fileptr
3162 * containing a start match. Is there a start on this
3163 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003164 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003165 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003166 start_col += startmatch.rm_so;
3167 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003168 if (regexec(tmpcolor->end, start_line->data +
3169 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003170 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003171 REG_NOTBOL) == REG_NOMATCH)
3172 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003173 break;
3174 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003175 if (regexec(&tmpcolor->start, start_line->data +
3176 start_col, 1, &startmatch,
3177 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003178 /* No later start on this line. */
3179 goto step_two;
3180 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003181 /* Indeed, there is a start not followed on this line by
3182 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003183
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003184 /* We have already checked that there is no end before
3185 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003186 * the start at all? We don't paint unterminated
3187 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003188 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003189 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003190 regexec(tmpcolor->end, end_line->data, 1,
3191 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003192 end_line = end_line->next;
3193
3194 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003195 if (end_line == NULL || (end_line == fileptr &&
3196 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003197 goto step_two;
3198
3199 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003200 if (end_line != fileptr)
3201 /* If the start of fileptr is on a different line
3202 * from the end, paintlen is -1, meaning that
3203 * everything on the line gets painted. */
3204 paintlen = -1;
3205 else
3206 /* Otherwise, paintlen is the expanded location of
3207 * the end of the match minus the expanded location
3208 * of the beginning of the page. */
3209 paintlen = actual_x(converted,
3210 strnlenpt(fileptr->data, endmatch.rm_eo) -
3211 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003212
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003213 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003214
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003215 step_two:
3216 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003217 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003218
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003219 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003220 if (regexec(&tmpcolor->start,
3221 fileptr->data + start_col, 1, &startmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003222 (start_col == 0) ? 0 :
3223 REG_NOTBOL) == REG_NOMATCH ||
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003224 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003225 /* No more starts on this line. */
3226 break;
3227 /* Translate the match to be relative to the
3228 * beginning of the line. */
3229 startmatch.rm_so += start_col;
3230 startmatch.rm_eo += start_col;
3231
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003232 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003233 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003234 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003235 x_start = strnlenpt(fileptr->data,
3236 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003237
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003238 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003239
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003240 if (regexec(tmpcolor->end,
3241 fileptr->data + startmatch.rm_eo, 1, &endmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003242 (startmatch.rm_eo == 0) ? 0 :
3243 REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003244 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003245 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003246 endmatch.rm_so += startmatch.rm_eo;
3247 endmatch.rm_eo += startmatch.rm_eo;
3248 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003249 * appear on this page, and is the match more
3250 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003251 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003252 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003253 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003254 strnlenpt(fileptr->data,
3255 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003256
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003257 assert(0 <= x_start && x_start < COLS);
3258
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003259 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003260 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003261 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003262 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003263 /* There is no end on this line. But we haven't
3264 * yet looked for one on later lines. */
3265 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003266
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003267 while (end_line != NULL &&
3268 regexec(tmpcolor->end, end_line->data,
3269 0, NULL, 0) == REG_NOMATCH)
3270 end_line = end_line->next;
3271
3272 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003273 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003274
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003275 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003276 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003277 /* We painted to the end of the line, so
3278 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003279 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003280 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003281 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003282 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003283 }
3284 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003285
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003286 wattroff(edit, A_BOLD);
3287 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003288 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003289 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003290#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003291
Chris Allegretta7dd77682001-12-08 19:52:28 +00003292#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003293 if (ISSET(MARK_ISSET)
3294 && (fileptr->lineno <= mark_beginbuf->lineno
3295 || fileptr->lineno <= current->lineno)
3296 && (fileptr->lineno >= mark_beginbuf->lineno
3297 || fileptr->lineno >= current->lineno)) {
3298 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003299
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003300 const filestruct *top;
3301 /* Either current or mark_beginbuf, whichever is first. */
3302 size_t top_x;
3303 /* current_x or mark_beginx, corresponding to top. */
3304 const filestruct *bot;
3305 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003306 int x_start;
3307 /* Starting column for mvwaddnstr. Zero-based. */
3308 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003309 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003310 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003311 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003312 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003313
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003314 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003315
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003316 if (top->lineno < fileptr->lineno || top_x < startpos)
3317 top_x = startpos;
3318 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3319 bot_x = endpos;
3320
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003321 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003322 if (top_x < endpos && bot_x > startpos) {
3323 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003324
3325 /* x_start is the expanded location of the beginning of the
3326 * mark minus the beginning of the page. */
3327 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003328
3329 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003330 /* If the end of the mark is off the page, paintlen is
3331 * -1, meaning that everything on the line gets
3332 * painted. */
3333 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003334 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003335 /* Otherwise, paintlen is the expanded location of the
3336 * end of the mark minus the expanded location of the
3337 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003338 paintlen = strnlenpt(fileptr->data, bot_x) -
3339 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003340
3341 /* If x_start is before the beginning of the page, shift
3342 * paintlen x_start characters to compensate, and put
3343 * x_start at the beginning of the page. */
3344 if (x_start < 0) {
3345 paintlen += x_start;
3346 x_start = 0;
3347 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003348
3349 assert(x_start >= 0 && x_start <= strlen(converted));
3350
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003351 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003352
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003353 if (paintlen > 0)
3354 paintlen = actual_x(converted + index, paintlen);
3355
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003356 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003357 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003358 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003359 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003360 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003361 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003362#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003363}
3364
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003365/* Just update one line in the edit buffer. This is basically a wrapper
3366 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003367 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003368 * If fileptr != current, then index is considered 0. The line will be
3369 * displayed starting with fileptr->data[index]. Likely args are
3370 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003371void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003372{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003373 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003374 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003375 char *converted;
3376 /* fileptr->data converted to have tabs and control characters
3377 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003378 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003379
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003380 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003381
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003382 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003383
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003384 /* We assume the line numbers are valid. Is that really true? */
3385 assert(line < 0 || line == check_linenumbers(fileptr));
3386
3387 if (line < 0 || line >= editwinrows)
3388 return;
3389
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003390 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003391 mvwaddstr(edit, line, 0, hblank);
3392
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003393 /* Next, convert variables that index the line to their equivalent
3394 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003395 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003396 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003397
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003398 /* Expand the line, replacing tabs with spaces, and control
3399 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003400 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003401
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003402 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003403 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003404 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003405
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003406 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003407 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003408 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003409 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003410}
3411
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003412/* Return a nonzero value if we need an update after moving
3413 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003414 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003415int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003416{
3417 return
3418#ifndef NANO_SMALL
3419 ISSET(MARK_ISSET) ||
3420#endif
3421 get_page_start(old_pww) != get_page_start(placewewant);
3422}
3423
3424/* Return a nonzero value if we need an update after moving vertically.
3425 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003426 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003427int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003428{
3429 return
3430#ifndef NANO_SMALL
3431 ISSET(MARK_ISSET) ||
3432#endif
3433 get_page_start(old_pww) != get_page_start(placewewant);
3434}
3435
3436/* Scroll the edit window in the given direction and the given number
3437 * of lines, and draw new lines on the blank lines left after the
3438 * scrolling. direction is the direction to scroll, either UP or DOWN,
3439 * and nlines is the number of lines to scroll. Don't redraw the old
3440 * topmost or bottommost line (where we assume current is) before
3441 * scrolling or draw the new topmost or bottommost line after scrolling
3442 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003443 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003444void edit_scroll(updown direction, int nlines)
3445{
3446 filestruct *foo;
3447 int i, scroll_rows = 0;
3448
3449 /* Scrolling less than one line or more than editwinrows lines is
3450 * redundant, so don't allow it. */
3451 if (nlines < 1 || nlines > editwinrows)
3452 return;
3453
3454 /* Move the top line of the edit window up or down (depending on the
3455 * value of direction) nlines lines. If there are fewer lines of
3456 * text than that left, move it to the top or bottom line of the
3457 * file (depending on the value of direction). Keep track of
3458 * how many lines we moved in scroll_rows. */
3459 for (i = nlines; i > 0; i--) {
3460 if (direction == UP) {
3461 if (edittop->prev == NULL)
3462 break;
3463 edittop = edittop->prev;
3464 scroll_rows--;
3465 } else {
3466 if (edittop->next == NULL)
3467 break;
3468 edittop = edittop->next;
3469 scroll_rows++;
3470 }
3471 }
3472
3473 /* Scroll the text on the screen up or down scroll_rows lines,
3474 * depending on the value of direction. */
3475 scrollok(edit, TRUE);
3476 wscrl(edit, scroll_rows);
3477 scrollok(edit, FALSE);
3478
3479 foo = edittop;
3480 if (direction != UP) {
3481 int slines = editwinrows - nlines;
3482 for (; slines > 0 && foo != NULL; slines--)
3483 foo = foo->next;
3484 }
3485
3486 /* And draw new lines on the blank top or bottom lines of the edit
3487 * window, depending on the value of direction. Don't draw the new
3488 * topmost or new bottommost line. */
3489 while (scroll_rows != 0 && foo != NULL) {
3490 if (foo->next != NULL)
3491 update_line(foo, 0);
3492 if (direction == UP)
3493 scroll_rows++;
3494 else
3495 scroll_rows--;
3496 foo = foo->next;
3497 }
3498}
3499
3500/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003501 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003502void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003503{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003504 int do_refresh = need_vertical_update(0) ||
3505 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003506 const filestruct *foo;
3507
3508 /* If either old_current or current is offscreen, refresh the screen
3509 * and get out. */
3510 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3511 edittop->lineno + editwinrows || current->lineno <
3512 edittop->lineno || current->lineno >= edittop->lineno +
3513 editwinrows) {
3514 edit_refresh();
3515 return;
3516 }
3517
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003518 /* Update old_current and current if we're not on the first page
3519 * and/or we're not on the same page as before. If the mark is on,
3520 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003521 foo = old_current;
3522 while (foo != current) {
3523 if (do_refresh)
3524 update_line(foo, 0);
3525#ifndef NANO_SMALL
3526 if (!ISSET(MARK_ISSET))
3527#endif
3528 break;
3529 if (foo->lineno > current->lineno)
3530 foo = foo->prev;
3531 else
3532 foo = foo->next;
3533 }
3534 if (do_refresh)
3535 update_line(current, current_x);
3536}
3537
Chris Allegretta6df90f52002-07-19 01:08:59 +00003538/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003539void edit_refresh(void)
3540{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003541 if (current->lineno < edittop->lineno ||
3542 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003543 /* Note that edit_update() changes edittop so that it's in range
3544 * of current. Thus, when it then calls edit_refresh(), there
3545 * is no danger of getting an infinite loop. */
3546 edit_update(
3547#ifndef NANO_SMALL
3548 ISSET(SMOOTHSCROLL) ? NONE :
3549#endif
3550 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003551 else {
3552 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003553 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003554
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003555#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003556 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003557#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003558
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003559 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003560 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003561 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003562 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003563 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003564 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003565 }
3566 while (nlines < editwinrows) {
3567 mvwaddstr(edit, nlines, 0, hblank);
3568 nlines++;
3569 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003570 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003571 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003572 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003573}
3574
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003575/* A nice generic routine to update the edit buffer. We keep current in
3576 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003577void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003578{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003579 filestruct *foo = current;
3580
Chris Allegretta6df90f52002-07-19 01:08:59 +00003581 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003582 /* If location is CENTER, we move edittop up (editwinrows / 2)
3583 * lines. This puts current at the center of the screen. If
3584 * location is NONE, we move edittop up current_y lines if
3585 * current_y is in range of the screen, 0 lines if current_y is
3586 * less than 0, or (editwinrows - 1) lines if current_y is
3587 * greater than (editwinrows - 1). This puts current at the
3588 * same place on the screen as before, or at the top or bottom
3589 * of the screen if edittop is beyond either. */
3590 int goal;
3591
3592 if (location == CENTER)
3593 goal = editwinrows / 2;
3594 else {
3595 goal = current_y;
3596
3597 /* Limit goal to (editwinrows - 1) lines maximum. */
3598 if (goal > editwinrows - 1)
3599 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003600 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003601
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003602 for (; goal > 0 && foo->prev != NULL; goal--)
3603 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003604 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003605
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003606 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003607 edit_refresh();
3608}
3609
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003610/* Ask a simple yes/no question, specified in msg, on the statusbar.
3611 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3612 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003613int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003614{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003615 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003616 const char *yesstr; /* String of yes characters accepted. */
3617 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003618 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003619
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003620 /* yesstr, nostr, and allstr are strings of any length. Each string
3621 * consists of all characters accepted as a valid character for that
3622 * value. The first value will be the one displayed in the
3623 * shortcuts. Translators: if possible, specify both the shortcuts
3624 * for your language and English. For example, in French: "OoYy"
3625 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003626 yesstr = _("Yy");
3627 nostr = _("Nn");
3628 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003629
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003630 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003631 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003632
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003633 if (COLS < 32)
3634 width = COLS / 2;
3635
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003636 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003637 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003638
Chris Allegretta6232d662002-05-12 19:52:15 +00003639 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003640 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003641 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003642
3643 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003644 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003645 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003646 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003647 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003648
Chris Allegrettadb28e962003-01-28 01:23:40 +00003649 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003650 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003651 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003652
Chris Allegrettadb28e962003-01-28 01:23:40 +00003653 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003654 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003655 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003656
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003657 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003658
3659 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003660 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003661
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003662 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003663
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003664 wrefresh(bottomwin);
3665
Chris Allegrettadb28e962003-01-28 01:23:40 +00003666 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003667 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003668 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003669#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003670 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003671#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003672
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003673 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003674
3675 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003676 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003677#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003678 /* Look, ma! We get to duplicate lots of code from
3679 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003680 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003681 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003682
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003683 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003684 wenclose(bottomwin, mouse_y, mouse_x) &&
3685 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003686 int x = mouse_x / width;
3687 /* Did we click in the first column of shortcuts, or
3688 * the second? */
3689 int y = mouse_y - editwinrows - 3;
3690 /* Did we click in the first row of shortcuts? */
3691
3692 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3693
3694 /* x = 0 means they clicked Yes or No.
3695 * y = 0 means Yes or All. */
3696 ok = -2 * x * y + x - y + 1;
3697
3698 if (ok == 2 && !all)
3699 ok = -2;
3700 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003701 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003702#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003703 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003704 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003705 else if (strchr(yesstr, kbinput) != NULL)
3706 ok = 1;
3707 else if (strchr(nostr, kbinput) != NULL)
3708 ok = 0;
3709 else if (all && strchr(allstr, kbinput) != NULL)
3710 ok = 2;
3711 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003712
Chris Allegrettadb28e962003-01-28 01:23:40 +00003713 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003714}
3715
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003716void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003717{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003718 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003719 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003720 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003721 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003722 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003723 wnoutrefresh(bottomwin);
3724 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003725 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003726 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003727 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003728 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003729 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003730 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003731}
3732
3733void display_main_list(void)
3734{
3735 bottombars(main_list);
3736}
3737
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003738/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3739 * display the cursor position. Otherwise, we display it only if the
3740 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003741 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003742 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3743 * old_i and old_totsize. That way, we leave the current statusbar
3744 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003745void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003746{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003747 char c;
3748 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003749 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003750 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003751
Chris Allegrettad26ab912003-01-28 01:16:47 +00003752 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003753
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003754 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003755 old_totsize = totsize;
3756
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003757 c = current->data[current_x];
3758 f = current->next;
3759 current->data[current_x] = '\0';
3760 current->next = NULL;
3761 get_totals(fileage, current, NULL, &i);
3762 current->data[current_x] = c;
3763 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003764
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003765 /* Check whether totsize is correct. Else there is a bug
3766 * somewhere. */
3767 assert(current != filebot || i == totsize);
3768
Chris Allegrettad26ab912003-01-28 01:16:47 +00003769 if (constant && ISSET(DISABLE_CURPOS)) {
3770 UNSET(DISABLE_CURPOS);
3771 old_i = i;
3772 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003773 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003774 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003775
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003776 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003777 * unconditionally; otherwise, only display the position when the
3778 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003779 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003780 size_t xpt = xplustabs() + 1;
3781 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003782 int linepct = 100 * current->lineno / totlines;
3783 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003784 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003785
3786 statusbar(
3787 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3788 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003789 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003790 (unsigned long)i, (unsigned long)totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003791 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003792 }
3793
3794 old_i = i;
3795 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003796}
3797
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003798void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003799{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003800 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003801}
3802
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003803#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003804/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003805int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003806{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003807 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003808
3809 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3810 ptr++;
3811 j++;
3812 }
3813 if (j == COLS - 5) {
3814 /* Don't wrap at the first of two spaces following a period. */
3815 if (*ptr == ' ' && *(ptr + 1) == ' ')
3816 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003817 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003818 while (*ptr != ' ' && j > 0) {
3819 ptr--;
3820 j--;
3821 }
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003822 /* A word longer than (COLS - 5) chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003823 if (j == 0)
3824 j = COLS - 5;
3825 }
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003826
Chris Allegretta4640fe32003-02-10 03:10:03 +00003827 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003828
Chris Allegretta4640fe32003-02-10 03:10:03 +00003829 return j;
3830}
3831
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003832/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003833void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003834{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003835 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003836 /* The line number in help_text of the first displayed help
3837 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003838 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003839 /* no_more means the end of the help text is shown, so don't go
3840 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003841 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003842 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003843
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003844 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003845#ifndef DISABLE_MOUSE
3846 const shortcut *oldshortcut = currshortcut;
3847 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003848 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003849#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003850
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003851 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003852 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003853 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003854 blank_statusbar();
3855
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003856 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003857 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003858 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003859
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003860#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003861 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003862 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003863 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003864#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003865
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003866 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003867 /* Make sure that the help screen's shortcut list will actually
3868 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003869 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003870 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003871 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003872
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003873 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003874
3875 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003876 int i;
3877 int old_line = line;
3878 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003879 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003880
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003881 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003882#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003883 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003884 {
3885 int mouse_x, mouse_y;
3886 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3887 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003888 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003889#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003890 case NANO_NEXTPAGE_KEY:
3891 case NANO_NEXTPAGE_FKEY:
3892 if (!no_more)
3893 line += editwinrows - 2;
3894 break;
3895 case NANO_PREVPAGE_KEY:
3896 case NANO_PREVPAGE_FKEY:
3897 if (line > 0) {
3898 line -= editwinrows - 2;
3899 if (line < 0)
3900 line = 0;
3901 }
3902 break;
3903 case NANO_PREVLINE_KEY:
3904 if (line > 0)
3905 line--;
3906 break;
3907 case NANO_NEXTLINE_KEY:
3908 if (!no_more)
3909 line++;
3910 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003911 }
3912
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003913 if (line == old_line && kbinput != ERR)
3914 goto skip_redisplay;
3915
3916 blank_edit();
3917
3918 assert(COLS > 5);
3919
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003920 /* Calculate where in the text we should be, based on the
3921 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003922 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003923 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003924 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003925 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003926 }
3927
Chris Allegretta4640fe32003-02-10 03:10:03 +00003928 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003929 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003930
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003931 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003932 ptr += j;
3933 if (*ptr == '\n')
3934 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003935 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003936 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003937
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003938 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003939 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003940 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3941 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003942
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003943#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003944 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003945#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003946
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003947 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003948 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003949 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003950 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003951 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003952 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003953 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003954
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003955 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003956 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003957
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003958 /* The help_init() at the beginning allocated help_text. Since
3959 * help_text has now been written to the screen, we don't need it
3960 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003961 free(help_text);
3962 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003963}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003964#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003965
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003966/* Highlight the current word being replaced or spell checked. We
3967 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003968void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003969{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003970 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003971 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003972
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003973 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003974 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003975 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003976
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003977 assert(y > 0);
3978
3979 if (word_len > y)
3980 y--;
3981
Chris Allegrettafb62f732000-12-05 11:36:41 +00003982 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003983
Chris Allegrettafb62f732000-12-05 11:36:41 +00003984 if (highlight_flag)
3985 wattron(edit, A_REVERSE);
3986
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003987#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003988 /* This is so we can show zero-length regexes. */
3989 if (word_len == 0)
3990 waddstr(edit, " ");
3991 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003992#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003993 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003994
3995 if (word_len > y)
3996 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003997
3998 if (highlight_flag)
3999 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004000}
4001
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004002#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004003/* Dump the passed-in file structure to stderr. */
4004void dump_buffer(const filestruct *inptr)
4005{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004006 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004007 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004008 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004009 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004010 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00004011 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004012
4013 while (inptr != NULL) {
4014 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4015 inptr = inptr->next;
4016 }
4017}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004018
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004019/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004020void dump_buffer_reverse(void)
4021{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004022 const filestruct *fileptr = filebot;
4023
4024 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004025 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004026 fileptr = fileptr->prev;
4027 }
4028}
4029#endif /* DEBUG */
4030
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004031#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004032#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004033#define XLCREDIT_LEN 8
4034
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004035/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004036void do_credits(void)
4037{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004038 int crpos = 0, xlpos = 0;
4039 const char *credits[CREDIT_LEN] = {
4040 NULL, /* "The nano text editor" */
4041 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004042 VERSION,
4043 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004044 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004045 "Chris Allegretta",
4046 "Jordi Mallach",
4047 "Adam Rogoyski",
4048 "Rob Siemborski",
4049 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004050 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004051 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004052 "Ken Tyler",
4053 "Sven Guckes",
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004054 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00004055 "Pauli Virtanen",
4056 "Daniele Medri",
4057 "Clement Laforet",
4058 "Tedi Heriyanto",
4059 "Bill Soudan",
4060 "Christian Weisgerber",
4061 "Erik Andersen",
4062 "Big Gaute",
4063 "Joshua Jensen",
4064 "Ryan Krebs",
4065 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004066 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004067 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004068 "Plattsburgh State University",
4069 "Benet Laboratories",
4070 "Amy Allegretta",
4071 "Linda Young",
4072 "Jeremy Robichaud",
4073 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004074 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004075 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004076 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004077 "Thomas Dickey",
4078 "Pavel Curtis",
4079 "Zeyd Ben-Halim",
4080 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004081 NULL, /* "and anyone else we forgot..." */
4082 NULL, /* "Thank you for using nano!" */
4083 "",
4084 "",
4085 "",
4086 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004087 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004088 "",
4089 "",
4090 "",
4091 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004092 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004093 };
4094
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004095 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004096 N_("The nano text editor"),
4097 N_("version"),
4098 N_("Brought to you by:"),
4099 N_("Special thanks to:"),
4100 N_("The Free Software Foundation"),
4101 N_("For ncurses:"),
4102 N_("and anyone else we forgot..."),
4103 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004104 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004105
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004106 curs_set(0);
4107 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004108 scrollok(edit, TRUE);
4109 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004110 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004111 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004112 blank_statusbar();
4113 blank_bottombars();
4114 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004115 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004116 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004117
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004118 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
4119 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004120 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004121
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004122 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004123 char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004124 size_t start_x;
4125
David Lawrence Ramsey631242d2005-03-15 07:06:54 +00004126 /* Make sure every credit is a valid multibyte string, since
4127 * we can't dynamically set the credits to their multibyte
4128 * equivalents when we need to. Sigh... */
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004129 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004130 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004131
4132 what = mallocstrcpy(NULL, _(xlcredits[xlpos]));
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004133 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004134 } else
4135 what = make_mbstring(credits[crpos]);
4136
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004137 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004138 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
4139 start_x, what);
4140
4141 free(what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004142 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004143
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004144 napms(700);
4145 scroll(edit);
4146 wrefresh(edit);
4147 if (wgetch(edit) != ERR)
4148 break;
4149 napms(700);
4150 scroll(edit);
4151 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004152 }
4153
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004154 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004155 nodelay(edit, FALSE);
4156 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004157 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004158}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004159#endif