blob: f07d6d78a104c84b54cff0534723a87ad4475475 [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"
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000033
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +000034static int *key_buffer = NULL;
David Lawrence Ramsey74835712004-12-04 17:41:52 +000035 /* The default keystroke buffer,
36 * containing all the keystrokes we have
37 * at a given point. */
38static size_t key_buffer_len = 0;
39 /* The length of the default keystroke
40 * buffer. */
41static int statusblank = 0; /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000042 * we call statusbar(), before we
43 * actually blank the statusbar. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +000044static size_t statusbar_x = (size_t)-1;
45 /* The cursor position in answer. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000046static bool resetstatuspos = FALSE;
47 /* Should we reset the cursor position
48 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000049
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000050/* Control character compatibility:
51 *
52 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
53 * VT100, and VT220.
54 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
55 * VT220, and VT320.
56 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
57 * VT220, and VT320.
58 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
59 * VT220, and VT320.
60 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
61 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000062 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000063 * ANSI, VT100, and VT220, and which is Backspace under VT320.
64 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000065 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000066 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
67 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000068 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000069 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000070 * on which the VT320 sequences are translated by the keypad to KEY_DC
71 * and [nothing]. We work around this conflict via the REBIND_DELETE
72 * flag: if it's not set, we assume VT320 compatibility, and if it is,
73 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
74 * Hemel for helping work this conflict out.
75 *
76 * Escape sequence compatibility:
77 *
78 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000079 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000080 * console), xterm, rxvt, and Eterm. Among these, there are several
81 * conflicts and omissions, outlined as follows:
82 *
83 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
84 * (Ctrl-I is also Tab on ANSI, which we already support.)
85 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
86 * NumLock off on Linux console; the latter is omitted. (The editing
87 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000088 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000089 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
90 * latter is omitted. (Mouse input will only work properly if the
91 * extended keypad value KEY_MOUSE is generated on mouse events
92 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000093 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000094 * omitted. (The editing keypad is more important to have working
95 * than the function keys, because the functions of the former are not
96 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000097 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000098 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000099 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000100 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000101 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
102 * omitted. (The arrow keys, with or without modifiers, are more
103 * important to have working than the function keys, because the
104 * functions of the former are not arbitrary and the functions of the
105 * latter are.)
106 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
107 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000108 *
109 * Note that Center (5) on the numeric keypad with NumLock off can also
110 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000111
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000112#ifndef NANO_SMALL
113/* Reset all the input routines that rely on character sequences. */
114void reset_kbinput(void)
115{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000116 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000117 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000118 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000119}
120#endif
121
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000122/* Read in a sequence of keystrokes from win and save them in the
123 * default keystroke buffer. This should only be called when the
124 * default keystroke buffer is empty. */
125void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000126{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000127 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000128
129 /* If the keystroke buffer isn't empty, get out. */
130 if (key_buffer != NULL)
131 return;
132
133 /* Read in the first character using blocking input. */
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000134#ifndef NANO_SMALL
135 allow_pending_sigwinch(TRUE);
136#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000137
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000138 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000139
David Lawrence Ramseyc275dc52005-03-08 17:45:36 +0000140 /* If we get ERR when using blocking input, it means that the input
141 * source that we were using is gone, so die gracefully. */
142 if (input == ERR)
143 handle_hupterm(0);
144
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000145#ifndef NANO_SMALL
146 allow_pending_sigwinch(FALSE);
147#endif
148
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000149 /* Increment the length of the keystroke buffer, save the value of
150 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000151 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000152 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000153 key_buffer = (int *)nmalloc(sizeof(int));
154 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000155
156 /* Read in the remaining characters using non-blocking input. */
157 nodelay(win, TRUE);
158
159 while (TRUE) {
160#ifndef NANO_SMALL
161 allow_pending_sigwinch(TRUE);
162#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000163
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000164 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000165
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000166 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000167 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000168 break;
169
170 /* Otherwise, increment the length of the keystroke buffer, save
171 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000172 * if the keystroke is an extended keypad value or FALSE if it
173 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000174 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000175 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
176 sizeof(int));
177 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000178
179#ifndef NANO_SMALL
180 allow_pending_sigwinch(FALSE);
181#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000182 }
183
184 /* Switch back to non-blocking input. */
185 nodelay(win, FALSE);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000186
187#ifdef DEBUG
188 fprintf(stderr, "get_buffer(): key_buffer_len = %lu\n", (unsigned long)key_buffer_len);
189#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000190}
191
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000192/* Return the length of the default keystroke buffer. */
193size_t get_buffer_len(void)
194{
195 return key_buffer_len;
196}
197
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000198/* Add the contents of the keystroke buffer input to the default
199 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000200void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000201{
202#ifndef NANO_SMALL
203 allow_pending_sigwinch(TRUE);
204 allow_pending_sigwinch(FALSE);
205#endif
206
207 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000208 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000209 return;
210
211 /* If adding input would put the default keystroke buffer beyond
212 * maximum capacity, only add enough of input to put it at maximum
213 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000214 if (key_buffer_len + input_len < key_buffer_len)
215 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000216
217 /* Add the length of input to the length of the default keystroke
218 * buffer, and reallocate the default keystroke buffer so that it
219 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000220 key_buffer_len += input_len;
221 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
222 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000223
224 /* If the default keystroke buffer wasn't empty before, move its
225 * beginning forward far enough so that we can add input to its
226 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000227 if (key_buffer_len > input_len)
228 memmove(key_buffer + input_len, key_buffer,
229 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000230
231 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000232 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000233}
234
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000235/* Put back the character stored in kbinput, putting it in byte range
236 * beforehand. If meta_key is TRUE, put back the Escape character after
237 * putting back kbinput. If func_key is TRUE, put back the function key
238 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000239void unget_kbinput(int kbinput, bool meta_key, bool func_key)
240{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000241 if (!func_key)
242 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000243
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000244 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000245
246 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000247 kbinput = NANO_CONTROL_3;
248 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000249 }
250}
251
252/* Try to read input_len characters from the default keystroke buffer.
253 * If the default keystroke buffer is empty and win isn't NULL, try to
254 * read in more characters from win and add them to the default
255 * keystroke buffer before doing anything else. If the default
256 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000257int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000258{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000259 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000260
261#ifndef NANO_SMALL
262 allow_pending_sigwinch(TRUE);
263 allow_pending_sigwinch(FALSE);
264#endif
265
266 if (key_buffer_len == 0) {
267 if (win != NULL)
268 get_buffer(win);
269
270 if (key_buffer_len == 0)
271 return NULL;
272 }
273
274 /* If input_len is greater than the length of the default keystroke
275 * buffer, only read the number of characters in the default
276 * keystroke buffer. */
277 if (input_len > key_buffer_len)
278 input_len = key_buffer_len;
279
280 /* Subtract input_len from the length of the default keystroke
281 * buffer, and allocate the keystroke buffer input so that it
282 * has enough room for input_len keystrokes. */
283 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000284 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000285
286 /* Copy input_len characters from the beginning of the default
287 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000288 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000289
290 /* If the default keystroke buffer is empty, mark it as such. */
291 if (key_buffer_len == 0) {
292 free(key_buffer);
293 key_buffer = NULL;
294 /* If the default keystroke buffer isn't empty, move its
295 * beginning forward far enough back so that the keystrokes in input
296 * are no longer at its beginning. */
297 } else {
298 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000299 sizeof(int));
300 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
301 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000302 }
303
304 return input;
305}
306
307/* Read in a single character. If it's ignored, swallow it and go on.
308 * Otherwise, try to translate it from ASCII, meta key sequences, escape
309 * sequences, and/or extended keypad values. Set meta_key to TRUE when
310 * we get a meta key sequence, and set func_key to TRUE when we get an
311 * extended keypad value. Supported extended keypad values consist of
312 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
313 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
314 * the function keypad (F1-F16), and the numeric keypad with NumLock
315 * off. Assume nodelay(win) is FALSE. */
316int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
317{
318 int kbinput;
319
320 /* Read in a character and interpret it. Continue doing this until
321 * we get a recognized value or sequence. */
322 while ((kbinput = parse_kbinput(win, meta_key, func_key
323#ifndef NANO_SMALL
324 , FALSE
325#endif
326 )) == ERR);
327
328 return kbinput;
329}
330
331/* Translate ASCII characters, extended keypad values, and escape
332 * sequences into their corresponding key values. Set meta_key to TRUE
333 * when we get a meta key sequence, and set func_key to TRUE when we get
334 * a function key. Assume nodelay(win) is FALSE. */
335int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000336#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000337 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000338#endif
339 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000340
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000341{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000342 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000343 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000344
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000345#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000346 if (reset) {
347 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000348 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000349 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000350 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000351#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000352
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000353 *meta_key = FALSE;
354 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000355
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000356 /* Read in a character. */
357 while ((kbinput = get_input(win, 1)) == NULL);
358
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000359 switch (*kbinput) {
360 case ERR:
361 break;
362 case NANO_CONTROL_3:
363 /* Increment the escape counter. */
364 escapes++;
365 switch (escapes) {
366 case 1:
367 /* One escape: wait for more input. */
368 case 2:
369 /* Two escapes: wait for more input. */
370 break;
371 default:
372 /* More than two escapes: reset the escape counter
373 * and wait for more input. */
374 escapes = 0;
375 }
376 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000377#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000378 /* Since we don't change the default SIGWINCH handler when
379 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
380 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
381 case KEY_RESIZE:
382 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000383#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000384#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000385 case KEY_SHIFT_L:
386 case KEY_SHIFT_R:
387 case KEY_CONTROL_L:
388 case KEY_CONTROL_R:
389 case KEY_ALT_L:
390 case KEY_ALT_R:
391 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000392#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000393 default:
394 switch (escapes) {
395 case 0:
396 switch (*kbinput) {
397 case NANO_CONTROL_8:
398 retval = ISSET(REBIND_DELETE) ?
399 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
400 break;
401 case KEY_DOWN:
402 retval = NANO_NEXTLINE_KEY;
403 break;
404 case KEY_UP:
405 retval = NANO_PREVLINE_KEY;
406 break;
407 case KEY_LEFT:
408 retval = NANO_BACK_KEY;
409 break;
410 case KEY_RIGHT:
411 retval = NANO_FORWARD_KEY;
412 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000413#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000414 /* HP-UX 10 and 11 don't support KEY_HOME. */
415 case KEY_HOME:
416 retval = NANO_HOME_KEY;
417 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000418#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000419 case KEY_BACKSPACE:
420 retval = NANO_BACKSPACE_KEY;
421 break;
422 case KEY_DC:
423 retval = ISSET(REBIND_DELETE) ?
424 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
425 break;
426 case KEY_IC:
427 retval = NANO_INSERTFILE_KEY;
428 break;
429 case KEY_NPAGE:
430 retval = NANO_NEXTPAGE_KEY;
431 break;
432 case KEY_PPAGE:
433 retval = NANO_PREVPAGE_KEY;
434 break;
435 case KEY_ENTER:
436 retval = NANO_ENTER_KEY;
437 break;
438 case KEY_A1: /* Home (7) on numeric keypad
439 * with NumLock off. */
440 retval = NANO_HOME_KEY;
441 break;
442 case KEY_A3: /* PageUp (9) on numeric keypad
443 * with NumLock off. */
444 retval = NANO_PREVPAGE_KEY;
445 break;
446 case KEY_B2: /* Center (5) on numeric keypad
447 * with NumLock off. */
448 break;
449 case KEY_C1: /* End (1) on numeric keypad
450 * with NumLock off. */
451 retval = NANO_END_KEY;
452 break;
453 case KEY_C3: /* PageDown (4) on numeric
454 * keypad with NumLock off. */
455 retval = NANO_NEXTPAGE_KEY;
456 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000457#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000458 /* Slang doesn't support KEY_BEG. */
459 case KEY_BEG: /* Center (5) on numeric keypad
460 * with NumLock off. */
461 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000462#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000463#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000464 /* HP-UX 10 and 11 don't support KEY_END. */
465 case KEY_END:
466 retval = NANO_END_KEY;
467 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000468#endif
469#ifdef KEY_SUSPEND
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000470 /* Slang doesn't support KEY_SUSPEND. */
471 case KEY_SUSPEND:
472 retval = NANO_SUSPEND_KEY;
473 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000474#endif
475#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000476 /* Slang doesn't support KEY_SLEFT. */
477 case KEY_SLEFT:
478 retval = NANO_BACK_KEY;
479 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000480#endif
481#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000482 /* Slang doesn't support KEY_SRIGHT. */
483 case KEY_SRIGHT:
484 retval = NANO_FORWARD_KEY;
485 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000486#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000487 default:
488 retval = *kbinput;
489 break;
490 }
491 break;
492 case 1:
493 /* One escape followed by a non-escape: escape
494 * sequence mode. Reset the escape counter. If
495 * there aren't any other keys waiting, we have a
496 * meta key sequence, so set meta_key to TRUE and
497 * save the lowercase version of the non-escape
498 * character as the result. If there are other keys
499 * waiting, we have a true escape sequence, so
500 * interpret it. */
501 escapes = 0;
502 if (get_buffer_len() == 0) {
503 *meta_key = TRUE;
504 retval = tolower(*kbinput);
505 } else {
506 int *seq;
507 size_t seq_len;
508 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000509
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000510 /* Put back the non-escape character, get the
511 * complete escape sequence, translate the
512 * sequence into its corresponding key value,
513 * and save that as the result. */
514 unget_input(kbinput, 1);
515 seq_len = get_buffer_len();
516 seq = get_input(NULL, seq_len);
517 retval = get_escape_seq_kbinput(seq, seq_len,
518 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000519
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000520 /* If the escape sequence is unrecognized and
521 * not ignored, put back all of its characters
522 * except for the initial escape. */
523 if (retval == ERR && !ignore_seq)
524 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000525
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000526 free(seq);
527 }
528 break;
529 case 2:
530 /* Two escapes followed by one or more decimal
531 * digits: byte sequence mode. If the word
532 * sequence's range is limited to 2XX (the first
533 * digit is in the '0' to '2' range and it's the
534 * first digit, or it's in the '0' to '9' range and
535 * it's not the first digit), increment the byte
536 * sequence counter and interpret the digit. If the
537 * byte sequence's range is not limited to 2XX, fall
538 * through. */
539 if (('0' <= *kbinput && *kbinput <= '6' &&
540 byte_digits == 0) || ('0' <= *kbinput &&
541 *kbinput <= '9' && byte_digits > 0)) {
542 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000543
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000544 byte_digits++;
545 byte = get_byte_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000546#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000547 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000548#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000549 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000550
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000551 if (byte != ERR) {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +0000552 char *byte_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000553 int byte_mb_len, *seq, i;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000554
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000555 /* If we've read in a complete byte
556 * sequence, reset the byte sequence counter
557 * and the escape counter, and put back the
558 * corresponding byte value. */
559 byte_digits = 0;
560 escapes = 0;
561
562 /* Put back the multibyte equivalent of the
563 * byte value. */
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +0000564 byte_mb = make_mbchar(byte, &byte_mb_len);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000565
566 seq = (int *)nmalloc(byte_mb_len *
567 sizeof(int));
568
569 for (i = 0; i < byte_mb_len; i++)
570 seq[i] = (unsigned char)byte_mb[i];
571
572 unget_input(seq, byte_mb_len);
573
574 free(seq);
575 free(byte_mb);
576 }
577 } else {
578 /* Reset the escape counter. */
579 escapes = 0;
580 if (byte_digits == 0)
581 /* Two escapes followed by a non-decimal
582 * digit or a decimal digit that would
583 * create a byte sequence greater than 2XX,
584 * and we're not in the middle of a byte
585 * sequence: control character sequence
586 * mode. Interpret the control sequence and
587 * save the corresponding control character
588 * as the result. */
589 retval = get_control_kbinput(*kbinput);
590 else {
591 /* If we're in the middle of a byte
592 * sequence, reset the byte sequence counter
593 * and save the character we got as the
594 * result. */
595 byte_digits = 0;
596 retval = *kbinput;
597 }
598 }
599 break;
600 }
601 }
602
603 /* If we have a result and it's an extended keypad value (i.e, a
604 * value outside of byte range), set func_key to TRUE. */
605 if (retval != ERR)
606 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000607
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000608#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000609 fprintf(stderr, "parse_kbinput(): kbinput = %d, meta_key = %d, func_key = %d, escapes = %d, byte_digits = %d, retval = %d\n", *kbinput, (int)*meta_key, (int)*func_key, escapes, byte_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000610#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000611
612 /* Return the result. */
613 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000614}
615
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000616/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000617 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000618 * are generated when the keypad doesn't support the needed keys. If
619 * the escape sequence is recognized but we want to ignore it, return
620 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
621 * set ignore_seq to FALSE. Assume that Escape has already been read
622 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000623int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000624 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000625{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000626 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000627
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000628 *ignore_seq = FALSE;
629
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000630 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000631 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000632 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000633 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000634 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000635 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000636 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000637 case 'P': /* Esc O 2 P == F13 on
638 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000639 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000640 break;
641 case 'Q': /* Esc O 2 Q == F14 on
642 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000643 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000644 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000645 case 'R': /* Esc O 2 R == F15 on
646 * xterm. */
647 retval = KEY_F(15);
648 break;
649 case 'S': /* Esc O 2 S == F16 on
650 * xterm. */
651 retval = KEY_F(16);
652 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000653 }
654 }
655 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000656 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
657 case 'B': /* Esc O B == Down on
658 * VT100/VT320/xterm. */
659 case 'C': /* Esc O C == Right on
660 * VT100/VT320/xterm. */
661 case 'D': /* Esc O D == Left on
662 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000663 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000664 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000665 case 'E': /* Esc O E == Center (5) on numeric keypad
666 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000667 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000668 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000669 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000670 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000671 break;
672 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000673 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000674 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000675 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000676 * NumLock off on VT100/VT220/VT320/xterm/
677 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000678 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000679 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000680 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000681 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000682 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000683 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000684 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000685 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000686 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000687 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000688 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000689 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000690 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000691 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000692 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000693 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000694 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000695 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000696 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000697 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000698 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000699 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000700 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000701 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000702 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000703 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000704 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000705 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000706 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000707 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000708 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000709 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000710 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000711 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000712 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000713 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000714 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000715 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000716 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000717 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000718 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000719 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000720 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000721 * NumLock off on VT100/VT220/VT320/xterm/
722 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000723 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000724 break;
725 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000726 * NumLock off on VT100/VT220/VT320/xterm/
727 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000728 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000729 break;
730 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000731 * NumLock off on VT100/VT220/VT320/xterm/
732 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000733 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000734 break;
735 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000736 * NumLock off on VT100/VT220/VT320/xterm/
737 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000738 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000739 break;
740 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000741 * with NumLock off on VT100/VT220/VT320/
742 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000743 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000744 break;
745 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000746 * NumLock off on VT100/VT220/VT320/xterm/
747 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000748 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000749 break;
750 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000751 * with NumLock off on VT100/VT220/VT320/
752 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000753 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000754 break;
755 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000756 * with NumLock off on VT100/VT220/VT320/
757 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000758 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000759 break;
760 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000761 * with NumLock off on VT100/VT220/VT320/
762 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000763 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000764 break;
765 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000766 * keypad with NumLock off on VT100/VT220/
767 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000768 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000769 break;
770 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000771 * with NumLock off on VT100/VT220/VT320/
772 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000773 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000774 break;
775 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000776 * with NumLock off on VT100/VT220/VT320/
777 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000778 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000779 break;
780 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000781 * with NumLock off on VT100/VT220/VT320/
782 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000783 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000784 break;
785 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000786 * with NumLock off on VT100/VT220/VT320/
787 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000788 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000789 break;
790 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000791 * with NumLock off on VT100/VT220/VT320/
792 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000793 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000794 break;
795 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000796 * with NumLock off on VT100/VT220/VT320/
797 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000798 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000799 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000800 }
801 break;
802 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000803 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000804 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000805 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000806 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000807 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000808 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000809 break;
810 }
811 break;
812 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000813 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000814 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000815 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000816 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000817 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
818 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000819 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000820 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000821 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
822 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000823 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000824 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000825 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
826 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000827 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000828 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000829 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
830 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000831 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000832 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000833 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
834 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000835 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000836 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000837 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000838 * VT220/VT320/Linux console/
839 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000840 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000841 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000842 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000843 * VT220/VT320/Linux console/
844 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000845 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000846 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000847 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000848 * VT220/VT320/Linux console/
849 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000850 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000851 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000852 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000853 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000854 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000855 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000856 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000857 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000858 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
859 * xterm. */
860 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
861 * xterm. */
862 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
863 * xterm. */
864 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
865 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000866 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000867 break;
868 }
869 }
870 break;
871 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000872 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000873 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000874 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
875 * xterm. */
876 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
877 * xterm. */
878 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
879 * xterm. */
880 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
881 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000882 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000883 break;
884 }
885 }
886 break;
887 }
888 }
889 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000890 default: /* Esc [ 1 ~ == Home on
891 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000892 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000893 break;
894 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000895 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000896 break;
897 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000898 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000899 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000900 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000901 * VT220/VT320/Linux console/
902 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000903 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000904 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000905 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000906 * VT220/VT320/Linux console/
907 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000908 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000909 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000910 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000911 * VT220/VT320/Linux console/
912 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000913 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000914 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000915 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000916 * VT220/VT320/Linux console/
917 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000918 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000919 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000920 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000921 * VT220/VT320/Linux console/
922 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000923 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000924 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000925 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000926 * VT220/VT320/Linux console/
927 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000928 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000929 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000930 case '8': /* Esc [ 2 8 ~ == F15 on
931 * VT220/VT320/Linux console/
932 * rxvt/Eterm. */
933 retval = KEY_F(15);
934 break;
935 case '9': /* Esc [ 2 9 ~ == F16 on
936 * VT220/VT320/Linux console/
937 * rxvt/Eterm. */
938 retval = KEY_F(16);
939 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000940 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000941 * VT220/VT320/Linux console/
942 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000943 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000944 break;
945 }
946 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000947 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000948 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
949 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000950 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000951 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000952 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000953 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000954 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000955 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000956 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
957 * Linux console/xterm; Esc [ 5 ^ ==
958 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000959 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000960 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000961 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
962 * Linux console/xterm; Esc [ 6 ^ ==
963 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000964 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000965 break;
966 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000967 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000968 break;
969 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000970 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000971 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000972 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000973 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000974 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000975 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000976 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000977 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000978 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000979 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000980 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000981 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000982 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000983 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000984 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000985 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000986 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000987 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000988 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000989 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000990 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000991 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000992 case 'E': /* Esc [ E == Center (5) on numeric keypad
993 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000994 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000995 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000996 case 'F': /* Esc [ F == End on FreeBSD
997 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000998 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000999 break;
1000 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001001 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001002 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001003 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001004 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001005 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001006 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001007 break;
1008 case 'I': /* Esc [ I == PageUp on FreeBSD
1009 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001010 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001011 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001012 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001013 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001014 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001015 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001016 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001017 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001018 break;
1019 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001020 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001021 break;
1022 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001023 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001024 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001025 case 'P': /* Esc [ O P == F1 on
1026 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001027 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001028 break;
1029 case 'Q': /* Esc [ O Q == F2 on
1030 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001031 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001032 break;
1033 case 'R': /* Esc [ O R == F3 on
1034 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001035 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001036 break;
1037 case 'S': /* Esc [ O S == F4 on
1038 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001039 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001040 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001041 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001042 } else {
1043 /* Esc [ O == F3 on FreeBSD console. */
1044 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001045 }
1046 break;
1047 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001048 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001049 break;
1050 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001051 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001052 break;
1053 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001054 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001055 break;
1056 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001057 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001058 break;
1059 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001060 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001061 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001062 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001063 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001064 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001065 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001066 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001067 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001068 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001069 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001070 break;
1071 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001072 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001073 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001074 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001075 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001076 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001077 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001078 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001079 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001080 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001081 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001082 case 'c': /* Esc [ c == Shift-Right on rxvt/
1083 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001084 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001085 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001086 break;
1087 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001088 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001089 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001090 case 'A': /* Esc [ [ A == F1 on Linux
1091 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001092 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001093 break;
1094 case 'B': /* Esc [ [ B == F2 on Linux
1095 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001096 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001097 break;
1098 case 'C': /* Esc [ [ C == F3 on Linux
1099 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001100 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001101 break;
1102 case 'D': /* Esc [ [ D == F4 on Linux
1103 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001104 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001105 break;
1106 case 'E': /* Esc [ [ E == F5 on Linux
1107 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001108 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001109 break;
1110 }
1111 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001112 break;
1113 }
1114 break;
1115 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001116 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001117
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001118#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001119 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001120#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001121
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001122 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001123}
1124
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001125/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001126 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001127 * to many escape sequences. */
1128int get_escape_seq_abcd(int kbinput)
1129{
1130 switch (tolower(kbinput)) {
1131 case 'a':
1132 return NANO_PREVLINE_KEY;
1133 case 'b':
1134 return NANO_NEXTLINE_KEY;
1135 case 'c':
1136 return NANO_FORWARD_KEY;
1137 case 'd':
1138 return NANO_BACK_KEY;
1139 default:
1140 return ERR;
1141 }
1142}
1143
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001144/* Translate a byte sequence: turn a three-digit decimal number from
1145 * 000 to 255 into its corresponding byte value. */
1146int get_byte_kbinput(int kbinput
1147#ifndef NANO_SMALL
1148 , bool reset
1149#endif
1150 )
1151{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001152 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001153 int retval = ERR;
1154
1155#ifndef NANO_SMALL
1156 if (reset) {
1157 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001158 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001159 return ERR;
1160 }
1161#endif
1162
1163 /* Increment the byte digit counter. */
1164 byte_digits++;
1165
1166 switch (byte_digits) {
1167 case 1:
1168 /* One digit: reset the byte sequence holder and add the
1169 * digit we got to the 100's position of the byte sequence
1170 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001171 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001172 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001173 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001174 else
1175 /* If the character we got isn't a decimal digit, or if
1176 * it is and it would put the byte sequence out of byte
1177 * range, save it as the result. */
1178 retval = kbinput;
1179 break;
1180 case 2:
1181 /* Two digits: add the digit we got to the 10's position of
1182 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001183 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1184 '6' <= kbinput && kbinput <= '9'))
1185 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001186 else
1187 /* If the character we got isn't a decimal digit, or if
1188 * it is and it would put the byte sequence out of byte
1189 * range, save it as the result. */
1190 retval = kbinput;
1191 break;
1192 case 3:
1193 /* Three digits: add the digit we got to the 1's position of
1194 * the byte sequence holder, and save the corresponding word
1195 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001196 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1197 '6' <= kbinput && kbinput <= '9')) {
1198 byte += (kbinput - '0');
1199 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001200 } else
1201 /* If the character we got isn't a decimal digit, or if
1202 * it is and it would put the word sequence out of word
1203 * range, save it as the result. */
1204 retval = kbinput;
1205 break;
1206 default:
1207 /* More than three digits: save the character we got as the
1208 * result. */
1209 retval = kbinput;
1210 break;
1211 }
1212
1213 /* If we have a result, reset the byte digit counter and the byte
1214 * sequence holder. */
1215 if (retval != ERR) {
1216 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001217 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001218 }
1219
1220#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001221 fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte = %d, retval = %d\n", kbinput, byte_digits, byte, retval);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001222#endif
1223
1224 return retval;
1225}
1226
1227/* Translate a word sequence: turn a four-digit hexadecimal number from
1228 * 0000 to ffff (case-insensitive) into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001229int get_word_kbinput(int kbinput
1230#ifndef NANO_SMALL
1231 , bool reset
1232#endif
1233 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001234{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001235 static int word_digits = 0, word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001236 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001237
1238#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001239 if (reset) {
1240 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001241 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001242 return ERR;
1243 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001244#endif
1245
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001246 /* Increment the word digit counter. */
1247 word_digits++;
1248
1249 switch (word_digits) {
1250 case 1:
1251 /* One digit: reset the word sequence holder and add the
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001252 * digit we got to the 4096's position of the word sequence
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001253 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001254 word = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001255 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001256 word += (kbinput - '0') * 4096;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001257 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001258 word += (tolower(kbinput) + 10 - 'a') * 4096;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001259 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001260 /* If the character we got isn't a hexadecimal digit, or
1261 * if it is and it would put the word sequence out of
1262 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001263 retval = kbinput;
1264 break;
1265 case 2:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001266 /* Two digits: add the digit we got to the 256's position of
1267 * the word sequence holder. */
1268 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001269 word += (kbinput - '0') * 256;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001270 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001271 word += (tolower(kbinput) + 10 - 'a') * 256;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001272 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001273 /* If the character we got isn't a hexadecimal digit, or
1274 * if it is and it would put the word sequence out of
1275 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001276 retval = kbinput;
1277 break;
1278 case 3:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001279 /* Three digits: add the digit we got to the 16's position
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001280 * of the word sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001281 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001282 word += (kbinput - '0') * 16;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001283 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001284 word += (tolower(kbinput) + 10 - 'a') * 16;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001285 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001286 /* If the character we got isn't a hexadecimal digit, or
1287 * if it is and it would put the word sequence out of
1288 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001289 retval = kbinput;
1290 break;
1291 case 4:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001292 /* Four digits: add the digit we got to the 1's position of
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001293 * the word sequence holder, and save the corresponding word
1294 * value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001295 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001296 word += (kbinput - '0');
1297 retval = word;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001298 } else if ('a' <= tolower(kbinput) &&
1299 tolower(kbinput) <= 'f') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001300 word += (tolower(kbinput) + 10 - 'a');
1301 retval = word;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001302 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001303 /* If the character we got isn't a hexadecimal digit, or
1304 * if it is and it would put the word sequence out of
1305 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001306 retval = kbinput;
1307 break;
1308 default:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001309 /* More than four digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001310 * result. */
1311 retval = kbinput;
1312 break;
1313 }
1314
1315 /* If we have a result, reset the word digit counter and the word
1316 * sequence holder. */
1317 if (retval != ERR) {
1318 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001319 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001320 }
1321
1322#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001323 fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word = %d, retval = %d\n", kbinput, word_digits, word, retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001324#endif
1325
1326 return retval;
1327}
1328
1329/* Translate a control character sequence: turn an ASCII non-control
1330 * character into its corresponding control character. */
1331int get_control_kbinput(int kbinput)
1332{
1333 int retval;
1334
1335 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1336 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1337 kbinput == '`')
1338 retval = NANO_CONTROL_SPACE;
1339 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1340 else if ('3' <= kbinput && kbinput <= '7')
1341 retval = kbinput - 24;
1342 /* Ctrl-8 (Ctrl-?) */
1343 else if (kbinput == '8' || kbinput == '?')
1344 retval = NANO_CONTROL_8;
1345 /* Ctrl-A to Ctrl-_ */
1346 else if ('A' <= kbinput && kbinput <= '_')
1347 retval = kbinput - 64;
1348 /* Ctrl-a to Ctrl-~ */
1349 else if ('a' <= kbinput && kbinput <= '~')
1350 retval = kbinput - 96;
1351 else
1352 retval = kbinput;
1353
1354#ifdef DEBUG
1355 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1356#endif
1357
1358 return retval;
1359}
1360
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001361/* Put the output-formatted characters in output back into the default
1362 * keystroke buffer, so that they can be parsed and displayed as output
1363 * again. */
1364void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001365{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001366 int *input;
1367 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001368
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001369 if (output_len == 0)
1370 return;
1371
1372 input = (int *)nmalloc(output_len * sizeof(int));
1373 for (i = 0; i < output_len; i++)
1374 input[i] = (int)output[i];
1375 unget_input(input, output_len);
1376 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001377}
1378
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001379/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001380 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1381int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1382{
1383 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001384
1385 /* Turn off flow control characters if necessary so that we can type
1386 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001387 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001388 if (ISSET(PRESERVE))
1389 disable_flow_control();
1390 keypad(win, FALSE);
1391
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001392 /* Read in a stream of characters and interpret it if possible. */
1393 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001394
1395 /* Turn flow control characters back on if necessary and turn the
1396 * keypad back on now that we're done. */
1397 if (ISSET(PRESERVE))
1398 enable_flow_control();
1399 keypad(win, TRUE);
1400
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001401 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001402}
1403
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001404/* Read in a stream of all available characters, and return the length
1405 * of the string in kbinput_len. Translate the first few characters of
1406 * the input into the corresponding word value if possible. After that,
1407 * leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001408int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001409{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001410 int *kbinput, word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001411
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001412 /* Read in the first keystroke. */
1413 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001414
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001415 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001416 word = get_word_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001417#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001418 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001419#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001420 );
1421
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001422 /* If the first keystroke isn't a hexadecimal digit, put back the
1423 * first keystroke. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001424 if (word != ERR)
1425 unget_input(kbinput, 1);
1426 /* Otherwise, read in keystrokes until we have a complete word
1427 * sequence, and put back the corresponding word value. */
1428 else {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00001429 char *word_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001430 int word_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001431
1432 while (word == ERR) {
1433 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001434
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001435 word = get_word_kbinput(*kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001436#ifndef NANO_SMALL
1437 , FALSE
1438#endif
1439 );
1440 }
1441
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001442 /* Put back the multibyte equivalent of the word value. */
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00001443 word_mb = make_mbchar(word, &word_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001444
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001445 seq = (int *)nmalloc(word_mb_len * sizeof(int));
1446
1447 for (i = 0; i < word_mb_len; i++)
1448 seq[i] = (unsigned char)word_mb[i];
1449
1450 unget_input(seq, word_mb_len);
1451
1452 free(seq);
1453 free(word_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001454 }
1455
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001456 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001457 * result. */
1458 *kbinput_len = get_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001459 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001460
1461 return retval;
1462}
1463
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001464#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001465/* Check for a mouse event, and if one's taken place, save the
1466 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001467 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1468 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001469 * place on it, figure out which shortcut was clicked and put back the
1470 * equivalent keystroke(s). Return FALSE if no keystrokes were
1471 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001472 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001473bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001474{
1475 MEVENT mevent;
1476
1477 *mouse_x = -1;
1478 *mouse_y = -1;
1479
1480 /* First, get the actual mouse event. */
1481 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001482 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001483
1484 /* Save the screen coordinates where the mouse event took place. */
1485 *mouse_x = mevent.x;
1486 *mouse_y = mevent.y;
1487
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001488 /* If we're allowing shortcuts, the current shortcut list is being
1489 * displayed on the last two lines of the screen, and the mouse
1490 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001491 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001492 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1493 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001494 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001495 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001496 /* The number of shortcuts in the current shortcut list. */
1497 const shortcut *s = currshortcut;
1498 /* The actual shortcut we clicked on, starting at the first
1499 * one in the current shortcut list. */
1500
1501 /* Get the shortcut lists' length. */
1502 if (currshortcut == main_list)
1503 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001504 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001505 currslen = length_of_list(currshortcut);
1506
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001507 /* We don't show any more shortcuts than the main list
1508 * does. */
1509 if (currslen > MAIN_VISIBLE)
1510 currslen = MAIN_VISIBLE;
1511 }
1512
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001513 /* Calculate the width of each shortcut in the list (it's the
1514 * same for all of them). */
1515 if (currslen < 2)
1516 i = COLS / 6;
1517 else
1518 i = COLS / ((currslen / 2) + (currslen % 2));
1519
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001520 /* Calculate the y-coordinate relative to the beginning of
1521 * bottomwin. */
1522 j = *mouse_y - ((2 - no_more_space()) + 1) - editwinrows;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001523
1524 /* If we're on the statusbar, beyond the end of the shortcut
1525 * list, or beyond the end of a shortcut on the right side of
1526 * the screen, don't do anything. */
1527 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001528 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001529 j = (*mouse_x / i) * 2 + j;
1530 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001531 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001532
1533 /* Go through the shortcut list to determine which shortcut was
1534 * clicked. */
1535 for (; j > 0; j--)
1536 s = s->next;
1537
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001538 /* And put back the equivalent key. Assume that each shortcut
1539 * has, at the very least, an equivalent control key, an
1540 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001541 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001542 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001543 return TRUE;
1544 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001545 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001546 return TRUE;
1547 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001548 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001549 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001550}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001551#endif /* !DISABLE_MOUSE */
1552
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001553const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001554 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001555{
1556 const shortcut *s = s_list;
1557 size_t slen = length_of_list(s_list);
1558
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001559#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001560 fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %d, func_key = %d\n", *kbinput, (int)*meta_key, (int)*func_key);
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001561#endif
1562
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001563 /* Check for shortcuts. */
1564 for (; slen > 0; slen--) {
1565 /* We've found a shortcut if:
1566 *
1567 * 1. The key exists.
1568 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001569 * 3. meta_key is TRUE and the key is the primary or
1570 * miscellaneous meta sequence in the shortcut list.
1571 * 4. func_key is TRUE and the key is a function key in the
1572 * shortcut list. */
1573
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001574 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1575 (*meta_key == TRUE && (*kbinput == s->metaval ||
1576 *kbinput == s->miscval)) || (*func_key == TRUE &&
1577 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001578 break;
1579 }
1580
1581 s = s->next;
1582 }
1583
1584 /* Translate the shortcut to either its control key or its meta key
1585 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001586 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001587 if (slen > 0) {
1588 if (s->ctrlval != NANO_NO_KEY) {
1589 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001590 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001591 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001592 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001593 } else if (s->metaval != NANO_NO_KEY) {
1594 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001595 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001596 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001597 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001598 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001599 }
1600
1601 return NULL;
1602}
1603
1604#ifndef NANO_SMALL
1605const toggle *get_toggle(int kbinput, bool meta_key)
1606{
1607 const toggle *t = toggles;
1608
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001609#ifdef DEBUG
1610 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1611#endif
1612
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001613 /* Check for toggles. */
1614 for (; t != NULL; t = t->next) {
1615 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001616 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001617 if (meta_key && kbinput == t->val)
1618 break;
1619 }
1620
1621 return t;
1622}
1623#endif /* !NANO_SMALL */
1624
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001625int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001626 bool *ran_func, bool *finished, bool allow_funcs)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001627{
1628 int input;
1629 /* The character we read in. */
1630 static int *kbinput = NULL;
1631 /* The input buffer. */
1632 static size_t kbinput_len = 0;
1633 /* The length of the input buffer. */
1634 const shortcut *s;
1635 bool have_shortcut;
1636
1637 *s_or_t = FALSE;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001638 *ran_func = FALSE;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001639 *finished = FALSE;
1640
1641 /* Read in a character. */
1642 input = get_kbinput(bottomwin, meta_key, func_key);
1643
1644#ifndef DISABLE_MOUSE
1645 /* If we got a mouse click and it was on a shortcut, read in the
1646 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001647 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001648 if (do_mouse())
1649 input = get_kbinput(bottomwin, meta_key, func_key);
1650 else
1651 input = ERR;
1652 }
1653#endif
1654
1655 /* Check for a shortcut in the current list. */
1656 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1657
1658 /* If we got a shortcut from the current list, or a "universal"
1659 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1660 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1661 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1662 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1663 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001664 input == NANO_CUT_KEY ||
1665#ifndef NANO_SMALL
1666 input == NANO_NEXTWORD_KEY ||
1667#endif
1668 (*meta_key == TRUE && (
1669#ifndef NANO_SMALL
1670 input == NANO_PREVWORD_KEY ||
1671#endif
1672 input == NANO_VERBATIM_KEY)));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001673
1674 /* Set s_or_t to TRUE if we got a shortcut. */
1675 *s_or_t = have_shortcut;
1676
1677 if (allow_funcs) {
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001678 /* If we got a character, and it isn't a shortcut or toggle,
1679 * it's a normal text character. Display the warning if we're
1680 * in view mode, or add the character to the input buffer if
1681 * we're not. */
1682 if (input != ERR && *s_or_t == FALSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001683 /* If we're using restricted mode, the filename isn't blank,
1684 * and we're at the "Write File" prompt, disable text
1685 * input. */
1686 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1687 currshortcut != writefile_list) {
1688 kbinput_len++;
1689 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1690 sizeof(int));
1691 kbinput[kbinput_len - 1] = input;
1692 }
1693 }
1694
1695 /* If we got a shortcut, or if there aren't any other characters
1696 * waiting after the one we read in, we need to display all the
1697 * characters in the input buffer if it isn't empty. */
1698 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1699 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001700
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001701 /* Display all the characters in the input buffer at
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001702 * once, filtering out control characters. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001703 char *output = charalloc(kbinput_len + 1);
1704 size_t i;
1705 bool got_enter;
1706 /* Whether we got the Enter key. */
1707
1708 for (i = 0; i < kbinput_len; i++)
1709 output[i] = (char)kbinput[i];
1710 output[i] = '\0';
1711
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001712 do_statusbar_output(output, kbinput_len, &got_enter,
1713 FALSE);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001714
1715 free(output);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001716
1717 /* Empty the input buffer. */
1718 kbinput_len = 0;
1719 free(kbinput);
1720 kbinput = NULL;
1721 }
1722 }
1723
1724 if (have_shortcut) {
1725 switch (input) {
1726 /* Handle the "universal" statusbar prompt shortcuts. */
1727 case NANO_REFRESH_KEY:
1728 total_refresh();
1729 break;
1730 case NANO_HOME_KEY:
1731 do_statusbar_home();
1732 break;
1733 case NANO_END_KEY:
1734 do_statusbar_end();
1735 break;
1736 case NANO_FORWARD_KEY:
1737 do_statusbar_right();
1738 break;
1739 case NANO_BACK_KEY:
1740 do_statusbar_left();
1741 break;
1742 case NANO_BACKSPACE_KEY:
1743 /* If we're using restricted mode, the filename
1744 * isn't blank, and we're at the "Write File"
1745 * prompt, disable Backspace. */
1746 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1747 currshortcut != writefile_list)
1748 do_statusbar_backspace();
1749 break;
1750 case NANO_DELETE_KEY:
1751 /* If we're using restricted mode, the filename
1752 * isn't blank, and we're at the "Write File"
1753 * prompt, disable Delete. */
1754 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1755 currshortcut != writefile_list)
1756 do_statusbar_delete();
1757 break;
1758 case NANO_CUT_KEY:
1759 /* If we're using restricted mode, the filename
1760 * isn't blank, and we're at the "Write File"
1761 * prompt, disable Cut. */
1762 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1763 currshortcut != writefile_list)
1764 do_statusbar_cut_text();
1765 break;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001766#ifndef NANO_SMALL
1767 case NANO_NEXTWORD_KEY:
1768 do_statusbar_next_word();
1769 break;
1770 case NANO_PREVWORD_KEY:
1771 if (*meta_key == TRUE)
1772 do_statusbar_prev_word();
1773 break;
1774#endif
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001775 case NANO_VERBATIM_KEY:
1776 if (*meta_key == TRUE) {
1777 /* If we're using restricted mode, the filename
1778 * isn't blank, and we're at the "Write File"
1779 * prompt, disable verbatim input. */
1780 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001781 currshortcut != writefile_list) {
1782 bool got_enter;
1783 /* Whether we got the Enter key. */
1784
1785 do_statusbar_verbatim_input(&got_enter);
1786
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001787 /* If we got the Enter key, set input to the
1788 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001789 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001790 if (got_enter) {
1791 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001792 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001793 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001794 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001795 break;
1796 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001797 /* Handle the normal statusbar prompt shortcuts, setting
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001798 * ran_func to TRUE if we try to run their associated
1799 * functions and setting finished to TRUE to indicate
1800 * that we're done after trying to run their associated
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001801 * functions. */
1802 default:
1803 if (s->func != NULL) {
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001804 *ran_func = TRUE;
1805 if (!ISSET(VIEW_MODE) || s->viewok)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001806 s->func();
1807 }
1808 *finished = TRUE;
1809 }
1810 }
1811 }
1812
1813 return input;
1814}
1815
1816#ifndef DISABLE_MOUSE
1817bool do_statusbar_mouse(void)
1818{
1819 /* FIXME: If we clicked on a location in the statusbar, the cursor
1820 * should move to the location we clicked on. This functionality
1821 * should be in this function. */
1822 int mouse_x, mouse_y;
1823 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1824}
1825#endif
1826
1827void do_statusbar_home(void)
1828{
1829#ifndef NANO_SMALL
1830 if (ISSET(SMART_HOME)) {
1831 size_t statusbar_x_save = statusbar_x;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001832
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001833 statusbar_x = indent_length(answer);
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001834
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001835 if (statusbar_x == statusbar_x_save ||
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001836 statusbar_x == strlen(answer))
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001837 statusbar_x = 0;
1838 } else
1839#endif
1840 statusbar_x = 0;
1841}
1842
1843void do_statusbar_end(void)
1844{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001845 statusbar_x = strlen(answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001846}
1847
1848void do_statusbar_right(void)
1849{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001850 if (statusbar_x < strlen(answer))
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001851 statusbar_x = move_mbright(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001852}
1853
1854void do_statusbar_left(void)
1855{
1856 if (statusbar_x > 0)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001857 statusbar_x = move_mbleft(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001858}
1859
1860void do_statusbar_backspace(void)
1861{
1862 if (statusbar_x > 0) {
1863 do_statusbar_left();
1864 do_statusbar_delete();
1865 }
1866}
1867
1868void do_statusbar_delete(void)
1869{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001870 if (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001871 int char_buf_len = parse_mbchar(answer + statusbar_x, NULL,
1872 NULL, NULL);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001873 size_t line_len = strlen(answer + statusbar_x);
1874
1875 assert(statusbar_x < strlen(answer));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001876
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001877 charmove(answer + statusbar_x, answer + statusbar_x +
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001878 char_buf_len, strlen(answer) - statusbar_x -
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001879 char_buf_len + 1);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001880
1881 null_at(&answer, statusbar_x + line_len - char_buf_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001882 }
1883}
1884
1885void do_statusbar_cut_text(void)
1886{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001887 assert(answer != NULL);
1888
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001889#ifndef NANO_SMALL
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001890 if (ISSET(CUT_TO_END))
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001891 null_at(&answer, statusbar_x);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001892 else {
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001893#endif
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001894 null_at(&answer, 0);
1895 statusbar_x = 0;
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001896#ifndef NANO_SMALL
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001897 }
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001898#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001899}
1900
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001901#ifndef NANO_SMALL
1902void do_statusbar_next_word(void)
1903{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001904 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001905 int char_mb_len;
1906
1907 assert(answer != NULL);
1908
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001909 char_mb = charalloc(mb_cur_max());
1910
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001911 /* Move forward until we find the character after the last letter of
1912 * the current word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001913 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001914 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1915 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001916
1917 /* If we've found it, stop moving forward through the current
1918 * line. */
1919 if (!is_alnum_mbchar(char_mb))
1920 break;
1921
1922 statusbar_x += char_mb_len;
1923 }
1924
1925 /* Move forward until we find the first letter of the next word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001926 if (answer[statusbar_x] != '\0')
1927 statusbar_x += char_mb_len;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001928
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001929 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001930 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1931 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001932
1933 /* If we've found it, stop moving forward through the current
1934 * line. */
1935 if (is_alnum_mbchar(char_mb))
1936 break;
1937
1938 statusbar_x += char_mb_len;
1939 }
1940
1941 free(char_mb);
1942}
1943
1944void do_statusbar_prev_word(void)
1945{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001946 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001947 int char_mb_len;
1948 bool begin_line = FALSE;
1949
1950 assert(answer != NULL);
1951
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001952 char_mb = charalloc(mb_cur_max());
1953
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001954 /* Move backward until we find the character before the first letter
1955 * of the current word. */
1956 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001957 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1958 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001959
1960 /* If we've found it, stop moving backward through the current
1961 * line. */
1962 if (!is_alnum_mbchar(char_mb))
1963 break;
1964
1965 if (statusbar_x == 0)
1966 begin_line = TRUE;
1967 else
1968 statusbar_x = move_mbleft(answer, statusbar_x);
1969 }
1970
1971 /* Move backward until we find the last letter of the previous
1972 * word. */
1973 if (statusbar_x == 0)
1974 begin_line = TRUE;
1975 else
1976 statusbar_x = move_mbleft(answer, statusbar_x);
1977
1978 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001979 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1980 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001981
1982 /* If we've found it, stop moving backward through the current
1983 * line. */
1984 if (is_alnum_mbchar(char_mb))
1985 break;
1986
1987 if (statusbar_x == 0)
1988 begin_line = TRUE;
1989 else
1990 statusbar_x = move_mbleft(answer, statusbar_x);
1991 }
1992
1993 /* If we've found it, move backward until we find the character
1994 * before the first letter of the previous word. */
1995 if (!begin_line) {
1996 if (statusbar_x == 0)
1997 begin_line = TRUE;
1998 else
1999 statusbar_x = move_mbleft(answer, statusbar_x);
2000
2001 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002002 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
2003 NULL, NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002004
2005 /* If we've found it, stop moving backward through the
2006 * current line. */
2007 if (!is_alnum_mbchar(char_mb))
2008 break;
2009
2010 if (statusbar_x == 0)
2011 begin_line = TRUE;
2012 else
2013 statusbar_x = move_mbleft(answer, statusbar_x);
2014 }
2015
2016 /* If we've found it, move forward to the first letter of the
2017 * previous word. */
2018 if (!begin_line)
2019 statusbar_x += char_mb_len;
2020 }
2021
2022 free(char_mb);
2023}
2024#endif
2025
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002026void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002027{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002028 int *kbinput;
2029 size_t kbinput_len, i;
2030 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002031
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002032 *got_enter = FALSE;
2033
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002034 /* Read in all the verbatim characters. */
2035 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
2036
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002037 /* Display all the verbatim characters at once, not filtering out
2038 * control characters. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002039 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002040
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002041 for (i = 0; i < kbinput_len; i++)
2042 output[i] = (char)kbinput[i];
2043 output[i] = '\0';
2044
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002045 do_statusbar_output(output, kbinput_len, got_enter, TRUE);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002046
2047 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002048}
2049
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002050void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002051 *got_enter, bool allow_cntrls)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002052{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002053 size_t answer_len = strlen(answer), i = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002054 char *char_buf = charalloc(mb_cur_max());
2055 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002056
2057 assert(answer != NULL);
2058
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002059 *got_enter = FALSE;
2060
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002061 while (i < output_len) {
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002062 /* If allow_cntrls is FALSE, filter out nulls and newlines,
2063 * since they're control characters. */
2064 if (allow_cntrls) {
2065 /* Null to newline, if needed. */
2066 if (output[i] == '\0')
2067 output[i] = '\n';
2068 /* Newline to Enter, if needed. */
2069 else if (output[i] == '\n') {
2070 /* Set got_enter to TRUE to indicate that we got the
2071 * Enter key, put back the rest of the characters in
2072 * output so that they can be parsed and output again,
2073 * and get out. */
2074 *got_enter = TRUE;
2075 unparse_kbinput(output + i, output_len - i);
2076 return;
2077 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002078 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002079
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002080 /* Interpret the next multibyte character. If it's an invalid
2081 * multibyte character, interpret it as though it's a byte
2082 * character. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002083 char_buf_len = parse_mbchar(output + i, char_buf, NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002084
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002085 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002086
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002087 /* If allow_cntrls is FALSE, filter out a control character. */
2088 if (!allow_cntrls && is_cntrl_mbchar(output + i - char_buf_len))
2089 continue;
2090
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002091 /* More dangerousness fun =) */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002092 answer = charealloc(answer, answer_len + (char_buf_len * 2));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002093
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002094 assert(statusbar_x <= answer_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002095
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002096 charmove(&answer[statusbar_x + char_buf_len],
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002097 &answer[statusbar_x], answer_len - statusbar_x +
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002098 char_buf_len);
2099 charcpy(&answer[statusbar_x], char_buf, char_buf_len);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002100 answer_len += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002101
2102 do_statusbar_right();
2103 }
2104
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002105 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002106}
2107
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002108/* Return the placewewant associated with current_x, i.e, the zero-based
2109 * column position of the cursor. The value will be no smaller than
2110 * current_x. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002111size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002112{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002113 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002114}
2115
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002116/* actual_x() gives the index in str of the character displayed at
2117 * column xplus. That is, actual_x() is the largest value such that
2118 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2119size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002120{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002121 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002122 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002123 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002124 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002125
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002126 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002127
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002128 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002129 int str_len = parse_mbchar(str, NULL, NULL, &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002130
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002131 if (length > xplus)
2132 break;
2133
2134 i += str_len;
2135 str += str_len;
2136 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002137
Chris Allegretta6df90f52002-07-19 01:08:59 +00002138 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002139}
2140
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002141/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002142 * columns wide are the first size characters of str? */
2143size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002144{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002145 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002146 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002147
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002148 if (size == 0)
2149 return 0;
2150
2151 assert(str != NULL);
2152
2153 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002154 int str_len = parse_mbchar(str, NULL, NULL, &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002155
2156 str += str_len;
2157
2158 if (size <= str_len)
2159 break;
2160
2161 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002162 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002163
Chris Allegretta6df90f52002-07-19 01:08:59 +00002164 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002165}
2166
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002167/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002168size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002169{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002170 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002171}
2172
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002173void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002174{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002175 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002176}
2177
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002178void blank_topbar(void)
2179{
2180 if (!ISSET(MORE_SPACE))
2181 mvwaddstr(topwin, 1, 0, hblank);
2182}
2183
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002184void blank_edit(void)
2185{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002186 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002187 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002188 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002189}
2190
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002191void blank_statusbar(void)
2192{
2193 mvwaddstr(bottomwin, 0, 0, hblank);
2194}
2195
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002196void blank_bottombars(void)
2197{
2198 if (!ISSET(NO_HELP)) {
2199 mvwaddstr(bottomwin, 1, 0, hblank);
2200 mvwaddstr(bottomwin, 2, 0, hblank);
2201 }
2202}
2203
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002204void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002205{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002206 if (statusblank > 1)
2207 statusblank--;
2208 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
2209 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002210 blank_statusbar();
2211 wnoutrefresh(bottomwin);
2212 reset_cursor();
2213 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002214 }
2215}
2216
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002217/* Convert buf into a string that can be displayed on screen. The
2218 * caller wants to display buf starting with column start_col, and
2219 * extending for at most len columns. start_col is zero-based. len is
2220 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002221 * string is dynamically allocated, and should be freed. If dollars is
2222 * TRUE, the caller might put "$" at the beginning or end of the line if
2223 * it's too long. */
2224char *display_string(const char *buf, size_t start_col, size_t len, bool
2225 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002226{
2227 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002228 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002229 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002230 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002231 size_t alloc_len;
2232 /* The length of memory allocated for converted. */
2233 char *converted;
2234 /* The string we return. */
2235 size_t index;
2236 /* Current position in converted. */
2237
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002238 char *buf_mb = charalloc(mb_cur_max());
2239 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002240 bool bad_char;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002241
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002242 /* If dollars is TRUE, make room for the "$" at the end of the
2243 * line. */
2244 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2245 len--;
2246
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002247 if (len == 0)
2248 return mallocstrcpy(NULL, "");
2249
2250 start_index = actual_x(buf, start_col);
2251 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002252
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002253 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002254
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002255 /* Allocate enough space for the entire line. It should contain
2256 * (len + 2) multibyte characters at most. */
2257 alloc_len = mb_cur_max() * (len + 2);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002258
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002259 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002260 index = 0;
2261
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002262 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002263 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002264 /* We don't display all of buf[start_index] since it starts to
2265 * the left of the screen. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002266 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL,
2267 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002268
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002269 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002270 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002271 char *ctrl_buf_mb = charalloc(mb_cur_max());
2272 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002273
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002274 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2275 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002276
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002277 for (i = 0; i < ctrl_buf_mb_len; i++)
2278 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002279
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002280 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002281
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002282 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002283
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002284 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002285 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002286 }
2287#ifdef NANO_WIDE
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002288 else if (mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002289 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002290 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002291
2292 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002293 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002294#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002295 }
2296
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002297 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseybc149412005-02-11 20:23:00 +00002298 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, &bad_char,
2299 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002300
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002301 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002302#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002303 if (ISSET(WHITESPACE_DISPLAY)) {
2304 int i;
2305
2306 for (i = 0; i < whitespace_len[0]; i++)
2307 converted[index++] = whitespace[i];
2308 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002309#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002310 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002311 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002312 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002313 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002314 start_col++;
2315 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002316 /* If buf contains a control character, interpret it. If it
2317 * contains an invalid multibyte control character, interpret
2318 * that character as though it's a normal control character. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002319 } else if (is_cntrl_mbchar(buf_mb)) {
2320 char *ctrl_buf_mb = charalloc(mb_cur_max());
2321 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002322
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002323 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002324 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002325
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002326 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2327 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002328
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002329 for (i = 0; i < ctrl_buf_mb_len; i++)
2330 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002331
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002332 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002333
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002334 free(ctrl_buf_mb);
2335 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002336#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002337 if (ISSET(WHITESPACE_DISPLAY)) {
2338 int i;
2339
2340 for (i = whitespace_len[0]; i < whitespace_len[0] +
2341 whitespace_len[1]; i++)
2342 converted[index++] = whitespace[i];
2343 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002344#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002345 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002346 start_col++;
2347 } else {
2348 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002349
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002350#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002351 /* If buf contains an invalid multibyte non-control
2352 * character, interpret that character as though it's a
2353 * normal non-control character. */
2354 if (!ISSET(NO_UTF8) && bad_char) {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002355 char *bad_buf_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002356 int bad_buf_mb_len;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002357
David Lawrence Ramsey4c6956b2005-01-12 04:32:43 +00002358 bad_buf_mb = make_mbchar((unsigned char)*buf_mb,
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002359 &bad_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002360
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002361 for (i = 0; i < bad_buf_mb_len; i++)
2362 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002363
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002364 start_col += mbwidth(bad_buf_mb);
2365
2366 free(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002367 } else {
2368#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002369 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002370 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002371
2372 start_col += mbwidth(buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002373#ifdef NANO_WIDE
2374 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002375#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002376 }
2377
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002378 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002379 }
2380
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002381 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002382 converted[index] = '\0';
2383
2384 /* Make sure converted takes up no more than len columns. */
2385 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002386 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002387
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002388 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002389}
2390
Chris Allegretta7662c862003-01-13 01:35:15 +00002391/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002392 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002393 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002394 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002395 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002396void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002397{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002398 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002399 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002400
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002401 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002402
Chris Allegrettab3655b42001-10-22 03:15:31 +00002403 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002404 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002405
Chris Allegretta6df90f52002-07-19 01:08:59 +00002406 mvwaddstr(bottomwin, 0, 0, buf);
2407 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002408
2409 if (COLS > 1)
2410 waddch(bottomwin, x_real < wid ? ' ' : '$');
2411 if (COLS > 2) {
2412 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002413 char *expanded = display_string(inputbuf, page_start, wid,
2414 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002415
2416 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002417 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002418
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002419 waddstr(bottomwin, expanded);
2420 free(expanded);
2421 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2422 } else
2423 wmove(bottomwin, 0, COLS - 1);
David Lawrence Ramseyd37f6a32005-03-26 20:41:36 +00002424
Chris Allegrettab3655b42001-10-22 03:15:31 +00002425 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002426}
2427
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002428/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002429 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002430int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002431#ifndef NANO_SMALL
2432 historyheadtype *history_list,
2433#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002434 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002435#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002436 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002437#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002438 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002439{
2440 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002441 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002442 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002443 /* used by input_tab() */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002444 size_t answer_len = strlen(def);
Chris Allegretta598106e2002-01-19 01:59:37 +00002445
Chris Allegretta5beed502003-01-05 20:41:21 +00002446#ifndef NANO_SMALL
2447 /* for history */
2448 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00002449 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00002450 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002451 int last_kbinput = 0;
2452
2453 /* This variable is used in the search history code. use_cb == 0
2454 means that we're using the existing history and ignoring
2455 currentbuf. use_cb == 1 means that the entry in answer should be
2456 moved to currentbuf or restored from currentbuf to answer.
2457 use_cb == 2 means that the entry in currentbuf should be moved to
2458 answer or restored from answer to currentbuf. */
2459 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002460#endif
Chris Allegretta09fc4302003-01-16 22:16:38 +00002461
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002462 /* Only put statusbar_x at the end of the string if it's
2463 * uninitialized, if it would be past the end of the string as it
2464 * is, or if resetstatuspos is TRUE. Otherwise, leave it alone.
2465 * This is so the cursor position stays at the same place if a
2466 * prompt-changing toggle is pressed. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002467 if (statusbar_x == (size_t)-1 || statusbar_x > answer_len ||
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002468 resetstatuspos)
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002469 statusbar_x = answer_len;
Chris Allegretta09fc4302003-01-16 22:16:38 +00002470
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002471 answer = charealloc(answer, answer_len + 1);
2472 if (answer_len > 0)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002473 strcpy(answer, def);
2474 else
2475 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002476
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002477 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002478
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002479 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002480
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002481 /* Refresh the edit window before getting input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002482 wnoutrefresh(edit);
2483 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002484
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002485 /* If we're using restricted mode, we aren't allowed to change the
2486 * name of a file once it has one because that would allow writing
2487 * to files not specified on the command line. In this case,
2488 * disable all keys that would change the text if the filename isn't
2489 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002490 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002491 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002492 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002493
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002494 /* If we have a shortcut with an associated function, break out
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002495 * if we're finished after running or trying to run the
2496 * function. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002497 if (finished)
2498 break;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002499
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002500 assert(statusbar_x <= answer_len && answer_len == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002501
David Lawrence Ramsey22425a22005-04-16 15:57:19 +00002502 if (kbinput != NANO_TAB_KEY)
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002503 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00002504
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002505 switch (kbinput) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002506 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002507#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002508 /* Tab history completion. */
2509 if (history_list != NULL) {
2510 if (!complete || last_kbinput != NANO_TAB_KEY) {
2511 history_list->current =
2512 (historytype *)history_list;
2513 history_list->len = strlen(answer);
2514 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002515
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002516 if (history_list->len > 0) {
2517 complete = get_history_completion(history_list,
2518 answer);
2519 answer = mallocstrcpy(answer, complete);
2520 answer_len = strlen(answer);
2521 statusbar_x = answer_len;
2522 }
2523 }
2524#ifndef DISABLE_TABCOMP
2525 else
2526#endif
2527#endif
2528#ifndef DISABLE_TABCOMP
2529 if (allow_tabs) {
2530 answer = input_tab(answer, &statusbar_x, &tabbed,
2531 list);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002532 answer_len = strlen(answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002533 }
2534#endif
2535 break;
2536 case NANO_PREVLINE_KEY:
2537#ifndef NANO_SMALL
2538 if (history_list != NULL) {
2539 /* If currentbuf is NULL, or if use_cb is 1,
2540 * currentbuf isn't NULL, and currentbuf is
2541 * different from answer, it means that we're
2542 * scrolling up at the top of the search history,
2543 * and we need to save the current answer in
2544 * currentbuf. Do this and reset use_cb to 0. */
2545 if (currentbuf == NULL || (use_cb == 1 &&
2546 strcmp(currentbuf, answer) != 0)) {
2547 currentbuf = mallocstrcpy(currentbuf, answer);
2548 use_cb = 0;
2549 }
2550
2551 /* If currentbuf isn't NULL, use_cb is 2, and
2552 * currentbuf is different from answer, it means
2553 * that we're scrolling up at the bottom of the
2554 * search history, and we need to make the string in
2555 * currentbuf the current answer. Do this, blow
2556 * away currentbuf since we don't need it anymore,
2557 * and reset use_cb to 0. */
2558 if (currentbuf != NULL && use_cb == 2 &&
2559 strcmp(currentbuf, answer) != 0) {
2560 answer = mallocstrcpy(answer, currentbuf);
2561 free(currentbuf);
2562 currentbuf = NULL;
2563 answer_len = strlen(answer);
2564 use_cb = 0;
2565
2566 /* Otherwise, get the older search from the history
2567 * list and save it in answer. If there is no older
2568 * search, blank out answer. */
2569 } else if ((history =
2570 get_history_older(history_list)) != NULL) {
2571 answer = mallocstrcpy(answer, history);
2572 answer_len = strlen(history);
2573 } else {
2574 answer = mallocstrcpy(answer, "");
2575 answer_len = 0;
2576 }
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002577 statusbar_x = answer_len;
Chris Allegretta5beed502003-01-05 20:41:21 +00002578 }
Chris Allegretta327abda2003-01-17 05:04:17 +00002579#endif
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002580 break;
2581 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002582#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002583 if (history_list != NULL) {
2584 /* Get the newer search from the history list and
2585 * save it in answer. */
2586 if ((history =
2587 get_history_newer(history_list)) != NULL) {
2588 answer = mallocstrcpy(answer, history);
2589 answer_len = strlen(history);
2590 /* If currentbuf isn't NULL and use_cb isn't 2, it
2591 * means that we're scrolling down at the bottom of
2592 * the search history and we need to make the string
2593 * in currentbuf the current answer; do this, blow
2594 * away currentbuf since we don't need it anymore,
2595 * and set use_cb to 1. */
2596 } else if (currentbuf != NULL && use_cb != 2) {
2597 answer = mallocstrcpy(answer, currentbuf);
2598 answer_len = strlen(answer);
2599 free(currentbuf);
2600 currentbuf = NULL;
2601 use_cb = 1;
2602 /* Itherwise, if currentbuf is NULL and use_cb isn't
2603 * 2, it means that we're scrolling down at the
2604 * bottom of the search history and the current
2605 * answer (if it's not blank) needs to be saved in
2606 * currentbuf. Do this, blank out answer (if
2607 * necessary), and set use_cb to 2. */
2608 } else if (use_cb != 2) {
2609 if (answer[0] != '\0') {
2610 currentbuf = mallocstrcpy(currentbuf,
2611 answer);
2612 answer = mallocstrcpy(answer, "");
2613 }
2614 answer_len = 0;
2615 use_cb = 2;
Chris Allegrettac30fc242003-08-11 00:32:45 +00002616 }
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002617 statusbar_x = answer_len;
Chris Allegretta5beed502003-01-05 20:41:21 +00002618 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002619#endif
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002620 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002621 }
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002622
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002623#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002624 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002625#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002626 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002627 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002628 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002629
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002630 /* We finished putting in an answer or ran a normal shortcut's
2631 * associated function, so reset statusbar_x. */
2632 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
2633 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002634 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002635
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002636 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002637}
2638
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002639/* Ask a question on the statusbar. Answer will be stored in answer
2640 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2641 * otherwise, the valid shortcut key caught. def is any editable text
2642 * we want to put up by default.
2643 *
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002644 * The allow_tabs parameter tells whether or not to allow tab
2645 * completion. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002646int statusq(bool allow_tabs, const shortcut *s, const char *def,
2647#ifndef NANO_SMALL
2648 historyheadtype *which_history,
2649#endif
2650 const char *msg, ...)
2651{
2652 va_list ap;
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002653 char *foo = charalloc(((COLS - 4) * mb_cur_max()) + 1);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002654 int ret;
2655#ifndef DISABLE_TABCOMP
2656 bool list = FALSE;
2657#endif
2658
2659 bottombars(s);
2660
2661 va_start(ap, msg);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002662 vsnprintf(foo, (COLS - 4) * mb_cur_max(), msg, ap);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002663 va_end(ap);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002664 null_at(&foo, actual_x(foo, COLS - 4));
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002665
2666 ret = nanogetstr(allow_tabs, foo, def,
2667#ifndef NANO_SMALL
2668 which_history,
2669#endif
2670 s
2671#ifndef DISABLE_TABCOMP
2672 , &list
2673#endif
2674 );
2675 free(foo);
2676 resetstatuspos = FALSE;
2677
2678 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002679 case NANO_CANCEL_KEY:
2680 ret = -1;
2681 resetstatuspos = TRUE;
2682 break;
2683 case NANO_ENTER_KEY:
2684 ret = (answer[0] == '\0') ? -2 : 0;
2685 resetstatuspos = TRUE;
2686 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002687 }
2688 blank_statusbar();
2689
2690#ifdef DEBUG
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002691 fprintf(stderr, "answer = \"%s\"\n", answer);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002692#endif
2693
2694#ifndef DISABLE_TABCOMP
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002695 /* If we've done tab completion, there might be a list of
2696 * filename matches on the edit window at this point. Make sure
2697 * that they're cleared off. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002698 if (list)
2699 edit_refresh();
2700#endif
2701
2702 return ret;
2703}
2704
2705void statusq_abort(void)
2706{
2707 resetstatuspos = TRUE;
2708}
2709
Chris Allegrettaf717f982003-02-13 22:25:01 +00002710void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002711{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002712 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002713 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002714 size_t verlen = strlenpt(VERMSG) + 1;
2715 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002716 const char *prefix;
2717 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2718 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002719 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002720 const char *state;
2721 /* "Modified", "View", or spaces the length of "Modified".
2722 * Tells the state of this buffer. */
2723 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002724 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002725 char *exppath = NULL;
2726 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002727 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002728 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002729 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002730 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002731
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002732 assert(path != NULL || filename != NULL);
2733 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002734
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002735 wattron(topwin, A_REVERSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002736 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002737
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002738 if (COLS <= 5 || COLS - 5 < verlen)
2739 space = 0;
2740 else {
2741 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002742 /* Reserve 2/3 of the screen plus one column for after the
2743 * version message. */
2744 if (space < COLS - (COLS / 3) + 1)
2745 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002746 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002747
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002748 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002749 /* The version message should only take up 1/3 of the screen
2750 * minus one column. */
2751 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002752 waddstr(topwin, " ");
2753 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002754
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002755 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002756 state = _("Modified");
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002757 else if (ISSET(VIEW_MODE))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002758 state = _("View");
2759 else {
2760 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002761 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002762 state = &hblank[COLS - statelen];
2763 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002764 statelen = strnlenpt(state, COLS);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002765
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002766 /* We need a space before state. */
2767 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2768 statelen++;
2769
2770 assert(space >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002771
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002772 if (space == 0 || statelen >= space)
2773 goto the_end;
2774
2775#ifndef DISABLE_BROWSER
2776 if (path != NULL)
2777 prefix = _("DIR:");
2778 else
2779#endif
2780 if (filename[0] == '\0') {
2781 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002782 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002783 } else
2784 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002785
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002786 assert(statelen < space);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002787
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002788 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002789
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002790 /* If newfie is FALSE, we need a space after prefix. */
2791 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002792 prefixlen++;
2793
2794 if (path == NULL)
2795 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002796 if (space >= prefixlen + statelen)
2797 space -= prefixlen + statelen;
2798 else
2799 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002800 /* space is now the room we have for the file name. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002801
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002802 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002803 size_t lenpt = strlenpt(path), start_col;
2804
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002805 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002806
2807 if (dots) {
2808 start_col = lenpt - space + 3;
2809 space -= 3;
2810 } else
2811 start_col = 0;
2812
2813 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002814 }
2815
2816 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002817 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2818 /* The length of the expanded filename. */
2819
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002820 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002821 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002822 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002823 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002824 assert(strlenpt(prefix) + 1 == prefixlen);
2825
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002826 waddch(topwin, ' ');
2827 waddstr(topwin, exppath);
2828 }
2829 } else {
2830 /* We will say something like "File: ...ename". */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002831 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002832 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002833 goto the_end;
2834 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002835 waddnstr(topwin, "...", space + 3);
2836 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002837 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002838 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002839 }
2840
2841 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002842 free(exppath);
2843
2844 if (COLS <= 1 || statelen >= COLS - 1)
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002845 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002846 else {
2847 assert(COLS - statelen - 2 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002848
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002849 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002850 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
2851 actual_x(state, statelen));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002852 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002853
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002854 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002855
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002856 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002857 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002858 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002859}
2860
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002861/* If modified is not already set, set it and update titlebar. */
2862void set_modified(void)
2863{
2864 if (!ISSET(MODIFIED)) {
2865 SET(MODIFIED);
2866 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002867 }
2868}
2869
2870void statusbar(const char *msg, ...)
2871{
2872 va_list ap;
2873
2874 va_start(ap, msg);
2875
2876 /* Curses mode is turned off. If we use wmove() now, it will muck
2877 * up the terminal settings. So we just use vfprintf(). */
2878 if (curses_ended) {
2879 vfprintf(stderr, msg, ap);
2880 va_end(ap);
2881 return;
2882 }
2883
2884 /* Blank out the line. */
2885 blank_statusbar();
2886
2887 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002888 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002889 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002890#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002891 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002892
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002893 UNSET(WHITESPACE_DISPLAY);
2894#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002895 bar = charalloc(mb_cur_max() * (COLS - 3));
2896 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002897 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002898 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002899#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2900 if (old_whitespace)
2901 SET(WHITESPACE_DISPLAY);
2902#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002903 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002904 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002905 start_x = (COLS - foo_len - 4) / 2;
2906
2907 wmove(bottomwin, 0, start_x);
2908 wattron(bottomwin, A_REVERSE);
2909
2910 waddstr(bottomwin, "[ ");
2911 waddstr(bottomwin, foo);
2912 free(foo);
2913 waddstr(bottomwin, " ]");
2914 wattroff(bottomwin, A_REVERSE);
2915 wnoutrefresh(bottomwin);
2916 reset_cursor();
2917 wrefresh(edit);
2918 /* Leave the cursor at its position in the edit window, not
2919 * in the statusbar. */
2920 }
2921
2922 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002923 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002924}
2925
Chris Allegretta6232d662002-05-12 19:52:15 +00002926void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002927{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002928 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002929
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002930 if (ISSET(NO_HELP))
2931 return;
2932
Chris Allegretta6232d662002-05-12 19:52:15 +00002933 if (s == main_list) {
2934 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002935 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002936 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002937 slen = length_of_list(s);
2938
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002939 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002940 if (slen > MAIN_VISIBLE)
2941 slen = MAIN_VISIBLE;
2942 }
2943
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002944 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002945 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002946 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002947
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002948 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002949
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002950 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002951 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002952
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002953 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002954#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002955 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002956 keystr = _("Up");
2957 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002958#endif
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00002959 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002960
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002961 if (s->ctrlval == NANO_CONTROL_SPACE)
2962 strcpy(foo, "^ ");
2963 else if (s->ctrlval == NANO_CONTROL_8)
2964 strcpy(foo, "^?");
2965 /* Normal values. Assume that the shortcut has an
2966 * equivalent control key, meta key sequence, or both. */
2967 else if (s->ctrlval != NANO_NO_KEY)
2968 sprintf(foo, "^%c", s->ctrlval + 64);
2969 else if (s->metaval != NANO_NO_KEY)
2970 sprintf(foo, "M-%c", toupper(s->metaval));
2971
2972 keystr = foo;
2973#ifndef NANO_SMALL
2974 }
2975#endif
2976
2977 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002978 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002979 }
2980
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002981 wnoutrefresh(bottomwin);
2982 reset_cursor();
2983 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002984}
2985
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002986/* Write a shortcut key to the help area at the bottom of the window.
2987 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2988 * to write at most len characters, even if len is very small and
2989 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2990 * the whole string! We do not bother padding the entry with blanks. */
2991void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002992{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002993 size_t keystroke_len = strlenpt(keystroke) + 1;
2994
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002995 assert(keystroke != NULL && desc != NULL);
2996
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002997 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002998 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002999 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003000
3001 if (len > keystroke_len)
3002 len -= keystroke_len;
3003 else
3004 len = 0;
3005
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003006 if (len > 0) {
3007 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003008 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003009 }
3010}
3011
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003012/* And so start the display update routines. */
3013
3014#ifndef NDEBUG
3015int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003016{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003017 int check_line = 0;
3018 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00003019
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003020 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
3021 check_line++;
3022 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00003023}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003024#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00003025
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003026/* nano scrolls horizontally within a line in chunks. This function
3027 * returns the column number of the first character displayed in the
3028 * window when the cursor is at the given column. Note that
3029 * 0 <= column - get_page_start(column) < COLS. */
3030size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00003031{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003032 assert(COLS > 0);
3033 if (column == 0 || column < COLS - 1)
3034 return 0;
3035 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00003036 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003037 else if (COLS > 2)
3038 return column - (COLS - 2);
3039 else
3040 return column - (COLS - 1);
3041 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003042}
3043
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003044/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003045 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003046void reset_cursor(void)
3047{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003048 /* If we haven't opened any files yet, put the cursor in the top
3049 * left corner of the edit window and get out. */
3050 if (edittop == NULL || current == NULL) {
3051 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003052 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003053 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003054
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003055 current_y = current->lineno - edittop->lineno;
3056 if (current_y < editwinrows) {
3057 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003058 wmove(edit, current_y, x - get_page_start(x));
3059 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003060}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003061
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003062/* edit_add() takes care of the job of actually painting a line into the
3063 * edit window. fileptr is the line to be painted, at row yval of the
3064 * window. converted is the actual string to be written to the window,
3065 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003066 * characters. start is the column number of the first character of
3067 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003068 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003069void edit_add(const filestruct *fileptr, const char *converted, int
3070 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003071{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003072#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003073 size_t startpos = actual_x(fileptr->data, start);
3074 /* The position in fileptr->data of the leftmost character
3075 * that displays at least partially on the window. */
3076 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3077 /* The position in fileptr->data of the first character that is
3078 * completely off the window to the right.
3079 *
3080 * Note that endpos might be beyond the null terminator of the
3081 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003082#endif
3083
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003084 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003085 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003086
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003087 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003088 * just the text that needs it). */
3089 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003090
Chris Allegretta7dd77682001-12-08 19:52:28 +00003091#ifdef ENABLE_COLOR
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003092 if (colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003093 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003094
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003095 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3096 int x_start;
3097 /* Starting column for mvwaddnstr. Zero-based. */
3098 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003099 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003100 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003101 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003102 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003103 regmatch_t startmatch; /* match position for start_regexp */
3104 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003105
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003106 if (tmpcolor->bright)
3107 wattron(edit, A_BOLD);
3108 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003109 /* Two notes about regexec(). Return value 0 means there is
3110 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003111 * after the match. */
3112
3113 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003114 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003115 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003116
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003117 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003118 * last match. Even though two matches may overlap, we
3119 * want to ignore them, so that we can highlight
3120 * C-strings correctly. */
3121 while (k < endpos) {
3122 /* Note the fifth parameter to regexec(). It says
3123 * not to match the beginning-of-line character
3124 * unless k is 0. If regexec() returns REG_NOMATCH,
3125 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003126 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003127 &startmatch, (k == 0) ? 0 :
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003128 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003129 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003130 /* Translate the match to the beginning of the
3131 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003132 startmatch.rm_so += k;
3133 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003134 if (startmatch.rm_so == startmatch.rm_eo) {
3135 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003136 statusbar(
3137 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003138 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003139 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003140 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003141 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003142 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003143 x_start = strnlenpt(fileptr->data,
3144 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003145
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003146 index = actual_x(converted, x_start);
3147
3148 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003149 strnlenpt(fileptr->data,
3150 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003151
3152 assert(0 <= x_start && 0 <= paintlen);
3153
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003154 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003155 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003156 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003157 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003158 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003159 } else {
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003160 /* This is a multi-line regexp. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003161 * First, we have to see if the beginning of the line is
3162 * colored by a start on an earlier line, and an end on
3163 * this line or later.
3164 *
3165 * We find the first line before fileptr matching the
3166 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003167 * end, then go to step two. Otherwise, find the next
3168 * line after start_line matching the end. If that line
3169 * is not before fileptr, then paint the beginning of
3170 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003171 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003172 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003173 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003174 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003175 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003176
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003177 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003178 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003179 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003180 /* If there is an end on this line, there is no need
3181 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003182 if (regexec(tmpcolor->end, start_line->data, 0,
3183 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003184 goto step_two;
3185 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003186 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003187 /* No start found, so skip to the next step. */
3188 if (start_line == NULL)
3189 goto step_two;
3190 /* Now start_line is the first line before fileptr
3191 * containing a start match. Is there a start on this
3192 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003193 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003194 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003195 start_col += startmatch.rm_so;
3196 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003197 if (regexec(tmpcolor->end, start_line->data +
3198 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003199 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003200 REG_NOTBOL) == REG_NOMATCH)
3201 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003202 break;
3203 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003204 if (regexec(&tmpcolor->start, start_line->data +
3205 start_col, 1, &startmatch,
3206 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003207 /* No later start on this line. */
3208 goto step_two;
3209 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003210 /* Indeed, there is a start not followed on this line by
3211 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003212
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003213 /* We have already checked that there is no end before
3214 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003215 * the start at all? We don't paint unterminated
3216 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003217 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003218 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003219 regexec(tmpcolor->end, end_line->data, 1,
3220 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003221 end_line = end_line->next;
3222
3223 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003224 if (end_line == NULL || (end_line == fileptr &&
3225 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003226 goto step_two;
3227
3228 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003229 if (end_line != fileptr)
3230 /* If the start of fileptr is on a different line
3231 * from the end, paintlen is -1, meaning that
3232 * everything on the line gets painted. */
3233 paintlen = -1;
3234 else
3235 /* Otherwise, paintlen is the expanded location of
3236 * the end of the match minus the expanded location
3237 * of the beginning of the page. */
3238 paintlen = actual_x(converted,
3239 strnlenpt(fileptr->data, endmatch.rm_eo) -
3240 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003241
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003242 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003243
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003244 step_two:
3245 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003246 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003247
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003248 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003249 if (regexec(&tmpcolor->start,
3250 fileptr->data + start_col, 1, &startmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003251 (start_col == 0) ? 0 :
3252 REG_NOTBOL) == REG_NOMATCH ||
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003253 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003254 /* No more starts on this line. */
3255 break;
3256 /* Translate the match to be relative to the
3257 * beginning of the line. */
3258 startmatch.rm_so += start_col;
3259 startmatch.rm_eo += start_col;
3260
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003261 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003262 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003263 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003264 x_start = strnlenpt(fileptr->data,
3265 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003266
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003267 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003268
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003269 if (regexec(tmpcolor->end,
3270 fileptr->data + startmatch.rm_eo, 1, &endmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003271 (startmatch.rm_eo == 0) ? 0 :
3272 REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003273 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003274 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003275 endmatch.rm_so += startmatch.rm_eo;
3276 endmatch.rm_eo += startmatch.rm_eo;
3277 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003278 * appear on this page, and is the match more
3279 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003280 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003281 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003282 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003283 strnlenpt(fileptr->data,
3284 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003285
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003286 assert(0 <= x_start && x_start < COLS);
3287
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003288 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003289 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003290 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003291 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003292 /* There is no end on this line. But we haven't
3293 * yet looked for one on later lines. */
3294 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003295
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003296 while (end_line != NULL &&
3297 regexec(tmpcolor->end, end_line->data,
3298 0, NULL, 0) == REG_NOMATCH)
3299 end_line = end_line->next;
3300
3301 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003302 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003303
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003304 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003305 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003306 /* We painted to the end of the line, so
3307 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003308 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003309 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003310 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003311 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003312 }
3313 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003314
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003315 wattroff(edit, A_BOLD);
3316 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003317 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003318 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003319#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003320
Chris Allegretta7dd77682001-12-08 19:52:28 +00003321#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003322 if (ISSET(MARK_ISSET)
3323 && (fileptr->lineno <= mark_beginbuf->lineno
3324 || fileptr->lineno <= current->lineno)
3325 && (fileptr->lineno >= mark_beginbuf->lineno
3326 || fileptr->lineno >= current->lineno)) {
3327 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003328
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003329 const filestruct *top;
3330 /* Either current or mark_beginbuf, whichever is first. */
3331 size_t top_x;
3332 /* current_x or mark_beginx, corresponding to top. */
3333 const filestruct *bot;
3334 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003335 int x_start;
3336 /* Starting column for mvwaddnstr. Zero-based. */
3337 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003338 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003339 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003340 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003341 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003342
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003343 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003344
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003345 if (top->lineno < fileptr->lineno || top_x < startpos)
3346 top_x = startpos;
3347 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3348 bot_x = endpos;
3349
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003350 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003351 if (top_x < endpos && bot_x > startpos) {
3352 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003353
3354 /* x_start is the expanded location of the beginning of the
3355 * mark minus the beginning of the page. */
3356 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003357
3358 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003359 /* If the end of the mark is off the page, paintlen is
3360 * -1, meaning that everything on the line gets
3361 * painted. */
3362 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003363 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003364 /* Otherwise, paintlen is the expanded location of the
3365 * end of the mark minus the expanded location of the
3366 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003367 paintlen = strnlenpt(fileptr->data, bot_x) -
3368 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003369
3370 /* If x_start is before the beginning of the page, shift
3371 * paintlen x_start characters to compensate, and put
3372 * x_start at the beginning of the page. */
3373 if (x_start < 0) {
3374 paintlen += x_start;
3375 x_start = 0;
3376 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003377
3378 assert(x_start >= 0 && x_start <= strlen(converted));
3379
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003380 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003381
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003382 if (paintlen > 0)
3383 paintlen = actual_x(converted + index, paintlen);
3384
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003385 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003386 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003387 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003388 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003389 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003390 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003391#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003392}
3393
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003394/* Just update one line in the edit buffer. This is basically a wrapper
3395 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003396 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003397 * If fileptr != current, then index is considered 0. The line will be
3398 * displayed starting with fileptr->data[index]. Likely args are
3399 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003400void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003401{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003402 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003403 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003404 char *converted;
3405 /* fileptr->data converted to have tabs and control characters
3406 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003407 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003408
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003409 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003410
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003411 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003412
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003413 /* We assume the line numbers are valid. Is that really true? */
3414 assert(line < 0 || line == check_linenumbers(fileptr));
3415
3416 if (line < 0 || line >= editwinrows)
3417 return;
3418
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003419 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003420 mvwaddstr(edit, line, 0, hblank);
3421
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003422 /* Next, convert variables that index the line to their equivalent
3423 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003424 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003425 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003426
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003427 /* Expand the line, replacing tabs with spaces, and control
3428 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003429 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003430
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003431 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003432 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003433 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003434
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003435 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003436 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003437 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003438 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003439}
3440
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003441/* Return a nonzero value if we need an update after moving
3442 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003443 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003444int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003445{
3446 return
3447#ifndef NANO_SMALL
3448 ISSET(MARK_ISSET) ||
3449#endif
3450 get_page_start(old_pww) != get_page_start(placewewant);
3451}
3452
3453/* Return a nonzero value if we need an update after moving vertically.
3454 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003455 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003456int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003457{
3458 return
3459#ifndef NANO_SMALL
3460 ISSET(MARK_ISSET) ||
3461#endif
3462 get_page_start(old_pww) != get_page_start(placewewant);
3463}
3464
3465/* Scroll the edit window in the given direction and the given number
3466 * of lines, and draw new lines on the blank lines left after the
3467 * scrolling. direction is the direction to scroll, either UP or DOWN,
3468 * and nlines is the number of lines to scroll. Don't redraw the old
3469 * topmost or bottommost line (where we assume current is) before
3470 * scrolling or draw the new topmost or bottommost line after scrolling
3471 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003472 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003473void edit_scroll(updown direction, int nlines)
3474{
3475 filestruct *foo;
3476 int i, scroll_rows = 0;
3477
3478 /* Scrolling less than one line or more than editwinrows lines is
3479 * redundant, so don't allow it. */
3480 if (nlines < 1 || nlines > editwinrows)
3481 return;
3482
3483 /* Move the top line of the edit window up or down (depending on the
3484 * value of direction) nlines lines. If there are fewer lines of
3485 * text than that left, move it to the top or bottom line of the
3486 * file (depending on the value of direction). Keep track of
3487 * how many lines we moved in scroll_rows. */
3488 for (i = nlines; i > 0; i--) {
3489 if (direction == UP) {
3490 if (edittop->prev == NULL)
3491 break;
3492 edittop = edittop->prev;
3493 scroll_rows--;
3494 } else {
3495 if (edittop->next == NULL)
3496 break;
3497 edittop = edittop->next;
3498 scroll_rows++;
3499 }
3500 }
3501
3502 /* Scroll the text on the screen up or down scroll_rows lines,
3503 * depending on the value of direction. */
3504 scrollok(edit, TRUE);
3505 wscrl(edit, scroll_rows);
3506 scrollok(edit, FALSE);
3507
3508 foo = edittop;
3509 if (direction != UP) {
3510 int slines = editwinrows - nlines;
3511 for (; slines > 0 && foo != NULL; slines--)
3512 foo = foo->next;
3513 }
3514
3515 /* And draw new lines on the blank top or bottom lines of the edit
3516 * window, depending on the value of direction. Don't draw the new
3517 * topmost or new bottommost line. */
3518 while (scroll_rows != 0 && foo != NULL) {
3519 if (foo->next != NULL)
3520 update_line(foo, 0);
3521 if (direction == UP)
3522 scroll_rows++;
3523 else
3524 scroll_rows--;
3525 foo = foo->next;
3526 }
3527}
3528
3529/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003530 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003531void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003532{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003533 int do_refresh = need_vertical_update(0) ||
3534 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003535 const filestruct *foo;
3536
3537 /* If either old_current or current is offscreen, refresh the screen
3538 * and get out. */
3539 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3540 edittop->lineno + editwinrows || current->lineno <
3541 edittop->lineno || current->lineno >= edittop->lineno +
3542 editwinrows) {
3543 edit_refresh();
3544 return;
3545 }
3546
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003547 /* Update old_current and current if we're not on the first page
3548 * and/or we're not on the same page as before. If the mark is on,
3549 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003550 foo = old_current;
3551 while (foo != current) {
3552 if (do_refresh)
3553 update_line(foo, 0);
3554#ifndef NANO_SMALL
3555 if (!ISSET(MARK_ISSET))
3556#endif
3557 break;
3558 if (foo->lineno > current->lineno)
3559 foo = foo->prev;
3560 else
3561 foo = foo->next;
3562 }
3563 if (do_refresh)
3564 update_line(current, current_x);
3565}
3566
Chris Allegretta6df90f52002-07-19 01:08:59 +00003567/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003568void edit_refresh(void)
3569{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003570 if (current->lineno < edittop->lineno ||
3571 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003572 /* Note that edit_update() changes edittop so that it's in range
3573 * of current. Thus, when it then calls edit_refresh(), there
3574 * is no danger of getting an infinite loop. */
3575 edit_update(
3576#ifndef NANO_SMALL
3577 ISSET(SMOOTHSCROLL) ? NONE :
3578#endif
3579 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003580 else {
3581 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003582 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003583
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003584#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003585 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003586#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003587
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003588 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003589 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003590 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003591 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003592 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003593 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003594 }
3595 while (nlines < editwinrows) {
3596 mvwaddstr(edit, nlines, 0, hblank);
3597 nlines++;
3598 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003599 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003600 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003601 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003602}
3603
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003604/* A nice generic routine to update the edit buffer. We keep current in
3605 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003606void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003607{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003608 filestruct *foo = current;
3609
Chris Allegretta6df90f52002-07-19 01:08:59 +00003610 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003611 /* If location is CENTER, we move edittop up (editwinrows / 2)
3612 * lines. This puts current at the center of the screen. If
3613 * location is NONE, we move edittop up current_y lines if
3614 * current_y is in range of the screen, 0 lines if current_y is
3615 * less than 0, or (editwinrows - 1) lines if current_y is
3616 * greater than (editwinrows - 1). This puts current at the
3617 * same place on the screen as before, or at the top or bottom
3618 * of the screen if edittop is beyond either. */
3619 int goal;
3620
3621 if (location == CENTER)
3622 goal = editwinrows / 2;
3623 else {
3624 goal = current_y;
3625
3626 /* Limit goal to (editwinrows - 1) lines maximum. */
3627 if (goal > editwinrows - 1)
3628 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003629 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003630
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003631 for (; goal > 0 && foo->prev != NULL; goal--)
3632 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003633 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003634
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003635 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003636 edit_refresh();
3637}
3638
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003639/* Ask a simple yes/no question, specified in msg, on the statusbar.
3640 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3641 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003642int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003643{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003644 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003645 const char *yesstr; /* String of yes characters accepted. */
3646 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003647 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003648
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003649 /* yesstr, nostr, and allstr are strings of any length. Each string
David Lawrence Ramseydcb4e3a2005-04-08 20:27:02 +00003650 * consists of all single-byte characters accepted as valid
3651 * characters for that value. The first value will be the one
3652 * displayed in the shortcuts. Translators: if possible, specify
3653 * both the shortcuts for your language and English. For example,
3654 * in French: "OoYy" for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003655 yesstr = _("Yy");
3656 nostr = _("Nn");
3657 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003658
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003659 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003660 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003661
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003662 if (COLS < 32)
3663 width = COLS / 2;
3664
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003665 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003666 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003667
Chris Allegretta6232d662002-05-12 19:52:15 +00003668 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003669 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003670 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003671
3672 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003673 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003674 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003675 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003676 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003677
Chris Allegrettadb28e962003-01-28 01:23:40 +00003678 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003679 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003680 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003681
Chris Allegrettadb28e962003-01-28 01:23:40 +00003682 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003683 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003684 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003685
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003686 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003687
3688 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003689 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003690
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003691 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003692
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003693 wrefresh(bottomwin);
3694
Chris Allegrettadb28e962003-01-28 01:23:40 +00003695 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003696 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003697 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003698#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003699 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003700#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003701
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003702 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003703
3704 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003705 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003706#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003707 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003708 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003709
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003710 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003711 wenclose(bottomwin, mouse_y, mouse_x) &&
3712 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003713 int x = mouse_x / width;
3714 /* Did we click in the first column of shortcuts, or
3715 * the second? */
3716 int y = mouse_y - editwinrows - 3;
3717 /* Did we click in the first row of shortcuts? */
3718
3719 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3720
3721 /* x = 0 means they clicked Yes or No.
3722 * y = 0 means Yes or All. */
3723 ok = -2 * x * y + x - y + 1;
3724
3725 if (ok == 2 && !all)
3726 ok = -2;
3727 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003728 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003729#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003730 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003731 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003732 else if (strchr(yesstr, kbinput) != NULL)
3733 ok = 1;
3734 else if (strchr(nostr, kbinput) != NULL)
3735 ok = 0;
3736 else if (all && strchr(allstr, kbinput) != NULL)
3737 ok = 2;
3738 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003739
Chris Allegrettadb28e962003-01-28 01:23:40 +00003740 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003741}
3742
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003743void total_update(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003744{
David Lawrence Ramsey04652512005-04-16 18:07:37 +00003745 clearok(curscr, TRUE);
3746 wrefresh(curscr);
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003747}
3748
3749void total_refresh(void)
3750{
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003751 total_update();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003752 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003753 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003754 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003755}
3756
3757void display_main_list(void)
3758{
3759 bottombars(main_list);
3760}
3761
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003762/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3763 * display the cursor position. Otherwise, we display it only if the
3764 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003765 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003766 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3767 * old_i and old_totsize. That way, we leave the current statusbar
3768 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003769void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003770{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003771 char c;
3772 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003773 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003774 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003775
Chris Allegrettad26ab912003-01-28 01:16:47 +00003776 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003777
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003778 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003779 old_totsize = totsize;
3780
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003781 c = current->data[current_x];
3782 f = current->next;
3783 current->data[current_x] = '\0';
3784 current->next = NULL;
3785 get_totals(fileage, current, NULL, &i);
3786 current->data[current_x] = c;
3787 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003788
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003789 /* Check whether totsize is correct. Else there is a bug
3790 * somewhere. */
3791 assert(current != filebot || i == totsize);
3792
Chris Allegrettad26ab912003-01-28 01:16:47 +00003793 if (constant && ISSET(DISABLE_CURPOS)) {
3794 UNSET(DISABLE_CURPOS);
3795 old_i = i;
3796 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003797 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003798 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003799
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003800 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003801 * unconditionally; otherwise, only display the position when the
3802 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003803 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003804 size_t xpt = xplustabs() + 1;
3805 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003806 int linepct = 100 * current->lineno / totlines;
3807 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003808 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003809
3810 statusbar(
3811 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3812 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003813 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003814 (unsigned long)i, (unsigned long)totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003815 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003816 }
3817
3818 old_i = i;
3819 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003820}
3821
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003822void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003823{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003824 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003825}
3826
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003827#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003828/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003829size_t help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003830{
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003831 int help_cols = (COLS > 24) ? COLS - 8 : 24;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003832
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003833 /* Try to break the line at (COLS - 8) columns if we have more than
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003834 * 24 columns, and at 24 columns otherwise. */
David Lawrence Ramsey40e211b2005-03-19 21:15:30 +00003835 size_t retval = break_line(ptr, help_cols, TRUE);
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003836 size_t retval_save = retval;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003837
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003838 /* Get the length of the entire line up to a null or a newline. */
3839 while (*(ptr + retval) != '\0' && *(ptr + retval) != '\n')
3840 retval += move_mbright(ptr + retval, 0);
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003841
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003842 /* If the entire line doesn't go more than 8 columns beyond where we
3843 * tried to break it, we should display it as-is. Otherwise, we
3844 * should display it only up to the break. */
3845 if (strnlenpt(ptr, retval) > help_cols + 8)
3846 retval = retval_save;
3847
3848 return retval;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003849}
3850
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003851/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003852void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003853{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003854 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003855 /* The line number in help_text of the first displayed help
3856 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003857 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003858 /* no_more means the end of the help text is shown, so don't go
3859 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003860 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003861 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003862
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003863 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003864#ifndef DISABLE_MOUSE
3865 const shortcut *oldshortcut = currshortcut;
3866 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003867 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003868#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003869
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003870 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003871 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003872 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003873 blank_statusbar();
3874
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003875 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003876 help_init();
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003877
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003878 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003879
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003880#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003881 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003882 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003883 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003884#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003885
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003886 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003887 /* Make sure that the help screen's shortcut list will actually
3888 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003889 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003890 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003891 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003892
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003893 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003894
3895 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003896 int i;
3897 int old_line = line;
3898 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003899 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003900
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003901 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003902#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003903 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003904 {
3905 int mouse_x, mouse_y;
3906 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3907 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003908 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003909#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003910 case NANO_PREVPAGE_KEY:
3911 case NANO_PREVPAGE_FKEY:
3912 if (line > 0) {
3913 line -= editwinrows - 2;
3914 if (line < 0)
3915 line = 0;
3916 }
3917 break;
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003918 case NANO_NEXTPAGE_KEY:
3919 case NANO_NEXTPAGE_FKEY:
3920 if (!no_more)
3921 line += editwinrows - 2;
3922 break;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003923 case NANO_PREVLINE_KEY:
3924 if (line > 0)
3925 line--;
3926 break;
3927 case NANO_NEXTLINE_KEY:
3928 if (!no_more)
3929 line++;
3930 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003931 }
3932
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003933 if (kbinput == NANO_REFRESH_KEY)
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003934 total_update();
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003935 else {
3936 if (line == old_line && kbinput != ERR)
3937 goto skip_redisplay;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003938
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003939 blank_edit();
3940 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003941
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003942 /* Calculate where in the text we should be, based on the
3943 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003944 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003945 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003946 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003947 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003948 }
3949
Chris Allegretta4640fe32003-02-10 03:10:03 +00003950 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003951 size_t j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003952
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003953 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003954 ptr += j;
3955 if (*ptr == '\n')
3956 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003957 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003958 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003959
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003960 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003961 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003962 } while (kbinput != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003963
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003964#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003965 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003966#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003967
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003968 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003969 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003970 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003971 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003972 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003973 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003974 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003975
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003976 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003977 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003978
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003979 /* The help_init() at the beginning allocated help_text. Since
3980 * help_text has now been written to the screen, we don't need it
3981 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003982 free(help_text);
3983 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003984}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003985#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003986
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003987/* Highlight the current word being replaced or spell checked. We
3988 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003989void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003990{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003991 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003992 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003993
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003994 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003995 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003996 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003997
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003998 assert(y > 0);
3999
4000 if (word_len > y)
4001 y--;
4002
Chris Allegrettafb62f732000-12-05 11:36:41 +00004003 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00004004
Chris Allegrettafb62f732000-12-05 11:36:41 +00004005 if (highlight_flag)
4006 wattron(edit, A_REVERSE);
4007
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004008#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00004009 /* This is so we can show zero-length regexes. */
4010 if (word_len == 0)
4011 waddstr(edit, " ");
4012 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004013#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004014 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004015
4016 if (word_len > y)
4017 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00004018
4019 if (highlight_flag)
4020 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004021}
4022
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004023#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004024/* Dump the passed-in file structure to stderr. */
4025void dump_buffer(const filestruct *inptr)
4026{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004027 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004028 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004029 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004030 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004031 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00004032 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004033
4034 while (inptr != NULL) {
4035 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4036 inptr = inptr->next;
4037 }
4038}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004039
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004040/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004041void dump_buffer_reverse(void)
4042{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004043 const filestruct *fileptr = filebot;
4044
4045 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004046 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004047 fileptr = fileptr->prev;
4048 }
4049}
4050#endif /* DEBUG */
4051
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004052#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004053#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004054#define XLCREDIT_LEN 8
4055
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004056/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004057void do_credits(void)
4058{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004059 int crpos = 0, xlpos = 0;
4060 const char *credits[CREDIT_LEN] = {
4061 NULL, /* "The nano text editor" */
4062 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004063 VERSION,
4064 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004065 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004066 "Chris Allegretta",
4067 "Jordi Mallach",
4068 "Adam Rogoyski",
4069 "Rob Siemborski",
4070 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004071 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004072 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004073 "Ken Tyler",
4074 "Sven Guckes",
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004075 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00004076 "Pauli Virtanen",
4077 "Daniele Medri",
4078 "Clement Laforet",
4079 "Tedi Heriyanto",
4080 "Bill Soudan",
4081 "Christian Weisgerber",
4082 "Erik Andersen",
4083 "Big Gaute",
4084 "Joshua Jensen",
4085 "Ryan Krebs",
4086 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004087 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004088 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004089 "Plattsburgh State University",
4090 "Benet Laboratories",
4091 "Amy Allegretta",
4092 "Linda Young",
4093 "Jeremy Robichaud",
4094 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004095 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004096 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004097 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004098 "Thomas Dickey",
4099 "Pavel Curtis",
4100 "Zeyd Ben-Halim",
4101 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004102 NULL, /* "and anyone else we forgot..." */
4103 NULL, /* "Thank you for using nano!" */
4104 "",
4105 "",
4106 "",
4107 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004108 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004109 "",
4110 "",
4111 "",
4112 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004113 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004114 };
4115
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004116 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004117 N_("The nano text editor"),
4118 N_("version"),
4119 N_("Brought to you by:"),
4120 N_("Special thanks to:"),
4121 N_("The Free Software Foundation"),
4122 N_("For ncurses:"),
4123 N_("and anyone else we forgot..."),
4124 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004125 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004126
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004127 curs_set(0);
4128 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004129 scrollok(edit, TRUE);
4130 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004131 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004132 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004133 blank_statusbar();
4134 blank_bottombars();
4135 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004136 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004137 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004138
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004139 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
4140 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004141 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004142
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004143 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004144 char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004145 size_t start_x;
4146
David Lawrence Ramsey631242d2005-03-15 07:06:54 +00004147 /* Make sure every credit is a valid multibyte string, since
4148 * we can't dynamically set the credits to their multibyte
4149 * equivalents when we need to. Sigh... */
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004150 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004151 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004152
4153 what = mallocstrcpy(NULL, _(xlcredits[xlpos]));
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004154 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004155 } else
4156 what = make_mbstring(credits[crpos]);
4157
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004158 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004159 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
4160 start_x, what);
4161
4162 free(what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004163 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004164
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004165 napms(700);
4166 scroll(edit);
4167 wrefresh(edit);
4168 if (wgetch(edit) != ERR)
4169 break;
4170 napms(700);
4171 scroll(edit);
4172 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004173 }
4174
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004175 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004176 nodelay(edit, FALSE);
4177 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004178 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004179}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004180#endif