blob: fb9651d73c6f18d1827f0518641f0ce4135a744e [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * winio.c *
4 * *
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00005 * Copyright (C) 1999-2005 Chris Allegretta *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00006 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
Jordi Mallach55381aa2004-11-17 23:17:05 +000022#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000025
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000026#include <stdarg.h>
27#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000028#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000029#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000030#include <ctype.h>
Chris Allegretta6232d662002-05-12 19:52:15 +000031#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000032#include "proto.h"
33#include "nano.h"
34
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +000035static int *key_buffer = NULL;
David Lawrence Ramsey74835712004-12-04 17:41:52 +000036 /* The default keystroke buffer,
37 * containing all the keystrokes we have
38 * at a given point. */
39static size_t key_buffer_len = 0;
40 /* The length of the default keystroke
41 * buffer. */
42static int statusblank = 0; /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000043 * we call statusbar(), before we
44 * actually blank the statusbar. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +000045static size_t statusbar_x = (size_t)-1;
46 /* The cursor position in answer. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000047static bool resetstatuspos = FALSE;
48 /* Should we reset the cursor position
49 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000050
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000051/* Control character compatibility:
52 *
53 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
54 * VT100, and VT220.
55 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
56 * VT220, and VT320.
57 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
58 * VT220, and VT320.
59 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
60 * VT220, and VT320.
61 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
62 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000063 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000064 * ANSI, VT100, and VT220, and which is Backspace under VT320.
65 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000066 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000067 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
68 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000069 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000070 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000071 * on which the VT320 sequences are translated by the keypad to KEY_DC
72 * and [nothing]. We work around this conflict via the REBIND_DELETE
73 * flag: if it's not set, we assume VT320 compatibility, and if it is,
74 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
75 * Hemel for helping work this conflict out.
76 *
77 * Escape sequence compatibility:
78 *
79 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000080 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000081 * console), xterm, rxvt, and Eterm. Among these, there are several
82 * conflicts and omissions, outlined as follows:
83 *
84 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
85 * (Ctrl-I is also Tab on ANSI, which we already support.)
86 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
87 * NumLock off on Linux console; the latter is omitted. (The editing
88 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000089 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000090 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
91 * latter is omitted. (Mouse input will only work properly if the
92 * extended keypad value KEY_MOUSE is generated on mouse events
93 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000094 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000095 * omitted. (The editing keypad is more important to have working
96 * than the function keys, because the functions of the former are not
97 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000098 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000099 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000100 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000101 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000102 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
103 * omitted. (The arrow keys, with or without modifiers, are more
104 * important to have working than the function keys, because the
105 * functions of the former are not arbitrary and the functions of the
106 * latter are.)
107 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
108 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000109 *
110 * Note that Center (5) on the numeric keypad with NumLock off can also
111 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000112
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000113#ifndef NANO_SMALL
114/* Reset all the input routines that rely on character sequences. */
115void reset_kbinput(void)
116{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000117 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000118 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000119 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000120}
121#endif
122
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000123/* Read in a sequence of keystrokes from win and save them in the
124 * default keystroke buffer. This should only be called when the
125 * default keystroke buffer is empty. */
126void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000127{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000128 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000129
130 /* If the keystroke buffer isn't empty, get out. */
131 if (key_buffer != NULL)
132 return;
133
134 /* Read in the first character using blocking input. */
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000135#ifndef NANO_SMALL
136 allow_pending_sigwinch(TRUE);
137#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000138
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000139 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000140
David Lawrence Ramseyc275dc52005-03-08 17:45:36 +0000141 /* If we get ERR when using blocking input, it means that the input
142 * source that we were using is gone, so die gracefully. */
143 if (input == ERR)
144 handle_hupterm(0);
145
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000146#ifndef NANO_SMALL
147 allow_pending_sigwinch(FALSE);
148#endif
149
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000150 /* Increment the length of the keystroke buffer, save the value of
151 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000152 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000153 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000154 key_buffer = (int *)nmalloc(sizeof(int));
155 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000156
157 /* Read in the remaining characters using non-blocking input. */
158 nodelay(win, TRUE);
159
160 while (TRUE) {
161#ifndef NANO_SMALL
162 allow_pending_sigwinch(TRUE);
163#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000164
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000165 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000166
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000167 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000168 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000169 break;
170
171 /* Otherwise, increment the length of the keystroke buffer, save
172 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000173 * if the keystroke is an extended keypad value or FALSE if it
174 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000175 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000176 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
177 sizeof(int));
178 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000179
180#ifndef NANO_SMALL
181 allow_pending_sigwinch(FALSE);
182#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000183 }
184
185 /* Switch back to non-blocking input. */
186 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000187}
188
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000189/* Return the length of the default keystroke buffer. */
190size_t get_buffer_len(void)
191{
192 return key_buffer_len;
193}
194
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000195/* Add the contents of the keystroke buffer input to the default
196 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000197void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000198{
199#ifndef NANO_SMALL
200 allow_pending_sigwinch(TRUE);
201 allow_pending_sigwinch(FALSE);
202#endif
203
204 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000205 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000206 return;
207
208 /* If adding input would put the default keystroke buffer beyond
209 * maximum capacity, only add enough of input to put it at maximum
210 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000211 if (key_buffer_len + input_len < key_buffer_len)
212 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000213
214 /* Add the length of input to the length of the default keystroke
215 * buffer, and reallocate the default keystroke buffer so that it
216 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000217 key_buffer_len += input_len;
218 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
219 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000220
221 /* If the default keystroke buffer wasn't empty before, move its
222 * beginning forward far enough so that we can add input to its
223 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000224 if (key_buffer_len > input_len)
225 memmove(key_buffer + input_len, key_buffer,
226 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000227
228 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000229 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000230}
231
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000232/* Put back the character stored in kbinput, putting it in byte range
233 * beforehand. If meta_key is TRUE, put back the Escape character after
234 * putting back kbinput. If func_key is TRUE, put back the function key
235 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000236void unget_kbinput(int kbinput, bool meta_key, bool func_key)
237{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000238 if (!func_key)
239 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000240
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000241 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000242
243 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000244 kbinput = NANO_CONTROL_3;
245 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000246 }
247}
248
249/* Try to read input_len characters from the default keystroke buffer.
250 * If the default keystroke buffer is empty and win isn't NULL, try to
251 * read in more characters from win and add them to the default
252 * keystroke buffer before doing anything else. If the default
253 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000254int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000255{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000256 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000257
258#ifndef NANO_SMALL
259 allow_pending_sigwinch(TRUE);
260 allow_pending_sigwinch(FALSE);
261#endif
262
263 if (key_buffer_len == 0) {
264 if (win != NULL)
265 get_buffer(win);
266
267 if (key_buffer_len == 0)
268 return NULL;
269 }
270
271 /* If input_len is greater than the length of the default keystroke
272 * buffer, only read the number of characters in the default
273 * keystroke buffer. */
274 if (input_len > key_buffer_len)
275 input_len = key_buffer_len;
276
277 /* Subtract input_len from the length of the default keystroke
278 * buffer, and allocate the keystroke buffer input so that it
279 * has enough room for input_len keystrokes. */
280 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000281 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000282
283 /* Copy input_len characters from the beginning of the default
284 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000285 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000286
287 /* If the default keystroke buffer is empty, mark it as such. */
288 if (key_buffer_len == 0) {
289 free(key_buffer);
290 key_buffer = NULL;
291 /* If the default keystroke buffer isn't empty, move its
292 * beginning forward far enough back so that the keystrokes in input
293 * are no longer at its beginning. */
294 } else {
295 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000296 sizeof(int));
297 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
298 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000299 }
300
301 return input;
302}
303
304/* Read in a single character. If it's ignored, swallow it and go on.
305 * Otherwise, try to translate it from ASCII, meta key sequences, escape
306 * sequences, and/or extended keypad values. Set meta_key to TRUE when
307 * we get a meta key sequence, and set func_key to TRUE when we get an
308 * extended keypad value. Supported extended keypad values consist of
309 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
310 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
311 * the function keypad (F1-F16), and the numeric keypad with NumLock
312 * off. Assume nodelay(win) is FALSE. */
313int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
314{
315 int kbinput;
316
317 /* Read in a character and interpret it. Continue doing this until
318 * we get a recognized value or sequence. */
319 while ((kbinput = parse_kbinput(win, meta_key, func_key
320#ifndef NANO_SMALL
321 , FALSE
322#endif
323 )) == ERR);
324
325 return kbinput;
326}
327
328/* Translate ASCII characters, extended keypad values, and escape
329 * sequences into their corresponding key values. Set meta_key to TRUE
330 * when we get a meta key sequence, and set func_key to TRUE when we get
331 * a function key. Assume nodelay(win) is FALSE. */
332int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000333#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000334 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000335#endif
336 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000337
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000338{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000339 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000340 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000341
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000342#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000343 if (reset) {
344 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000345 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000346 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000347 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000348#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000349
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000350 *meta_key = FALSE;
351 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000352
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000353 /* Read in a character. */
354 while ((kbinput = get_input(win, 1)) == NULL);
355
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000356 switch (*kbinput) {
357 case ERR:
358 break;
359 case NANO_CONTROL_3:
360 /* Increment the escape counter. */
361 escapes++;
362 switch (escapes) {
363 case 1:
364 /* One escape: wait for more input. */
365 case 2:
366 /* Two escapes: wait for more input. */
367 break;
368 default:
369 /* More than two escapes: reset the escape counter
370 * and wait for more input. */
371 escapes = 0;
372 }
373 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000374#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000375 /* Since we don't change the default SIGWINCH handler when
376 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
377 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
378 case KEY_RESIZE:
379 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000380#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000381#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000382 case KEY_SHIFT_L:
383 case KEY_SHIFT_R:
384 case KEY_CONTROL_L:
385 case KEY_CONTROL_R:
386 case KEY_ALT_L:
387 case KEY_ALT_R:
388 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000389#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000390 default:
391 switch (escapes) {
392 case 0:
393 switch (*kbinput) {
394 case NANO_CONTROL_8:
395 retval = ISSET(REBIND_DELETE) ?
396 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
397 break;
398 case KEY_DOWN:
399 retval = NANO_NEXTLINE_KEY;
400 break;
401 case KEY_UP:
402 retval = NANO_PREVLINE_KEY;
403 break;
404 case KEY_LEFT:
405 retval = NANO_BACK_KEY;
406 break;
407 case KEY_RIGHT:
408 retval = NANO_FORWARD_KEY;
409 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000410#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000411 /* HP-UX 10 and 11 don't support KEY_HOME. */
412 case KEY_HOME:
413 retval = NANO_HOME_KEY;
414 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000415#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000416 case KEY_BACKSPACE:
417 retval = NANO_BACKSPACE_KEY;
418 break;
419 case KEY_DC:
420 retval = ISSET(REBIND_DELETE) ?
421 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
422 break;
423 case KEY_IC:
424 retval = NANO_INSERTFILE_KEY;
425 break;
426 case KEY_NPAGE:
427 retval = NANO_NEXTPAGE_KEY;
428 break;
429 case KEY_PPAGE:
430 retval = NANO_PREVPAGE_KEY;
431 break;
432 case KEY_ENTER:
433 retval = NANO_ENTER_KEY;
434 break;
435 case KEY_A1: /* Home (7) on numeric keypad
436 * with NumLock off. */
437 retval = NANO_HOME_KEY;
438 break;
439 case KEY_A3: /* PageUp (9) on numeric keypad
440 * with NumLock off. */
441 retval = NANO_PREVPAGE_KEY;
442 break;
443 case KEY_B2: /* Center (5) on numeric keypad
444 * with NumLock off. */
445 break;
446 case KEY_C1: /* End (1) on numeric keypad
447 * with NumLock off. */
448 retval = NANO_END_KEY;
449 break;
450 case KEY_C3: /* PageDown (4) on numeric
451 * keypad with NumLock off. */
452 retval = NANO_NEXTPAGE_KEY;
453 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000454#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000455 /* Slang doesn't support KEY_BEG. */
456 case KEY_BEG: /* Center (5) on numeric keypad
457 * with NumLock off. */
458 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000459#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000460#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000461 /* HP-UX 10 and 11 don't support KEY_END. */
462 case KEY_END:
463 retval = NANO_END_KEY;
464 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000465#endif
466#ifdef KEY_SUSPEND
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000467 /* Slang doesn't support KEY_SUSPEND. */
468 case KEY_SUSPEND:
469 retval = NANO_SUSPEND_KEY;
470 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000471#endif
472#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000473 /* Slang doesn't support KEY_SLEFT. */
474 case KEY_SLEFT:
475 retval = NANO_BACK_KEY;
476 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000477#endif
478#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000479 /* Slang doesn't support KEY_SRIGHT. */
480 case KEY_SRIGHT:
481 retval = NANO_FORWARD_KEY;
482 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000483#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000484 default:
485 retval = *kbinput;
486 break;
487 }
488 break;
489 case 1:
490 /* One escape followed by a non-escape: escape
491 * sequence mode. Reset the escape counter. If
492 * there aren't any other keys waiting, we have a
493 * meta key sequence, so set meta_key to TRUE and
494 * save the lowercase version of the non-escape
495 * character as the result. If there are other keys
496 * waiting, we have a true escape sequence, so
497 * interpret it. */
498 escapes = 0;
499 if (get_buffer_len() == 0) {
500 *meta_key = TRUE;
501 retval = tolower(*kbinput);
502 } else {
503 int *seq;
504 size_t seq_len;
505 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000506
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000507 /* Put back the non-escape character, get the
508 * complete escape sequence, translate the
509 * sequence into its corresponding key value,
510 * and save that as the result. */
511 unget_input(kbinput, 1);
512 seq_len = get_buffer_len();
513 seq = get_input(NULL, seq_len);
514 retval = get_escape_seq_kbinput(seq, seq_len,
515 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000516
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000517 /* If the escape sequence is unrecognized and
518 * not ignored, put back all of its characters
519 * except for the initial escape. */
520 if (retval == ERR && !ignore_seq)
521 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000522
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000523 free(seq);
524 }
525 break;
526 case 2:
527 /* Two escapes followed by one or more decimal
528 * digits: byte sequence mode. If the word
529 * sequence's range is limited to 2XX (the first
530 * digit is in the '0' to '2' range and it's the
531 * first digit, or it's in the '0' to '9' range and
532 * it's not the first digit), increment the byte
533 * sequence counter and interpret the digit. If the
534 * byte sequence's range is not limited to 2XX, fall
535 * through. */
536 if (('0' <= *kbinput && *kbinput <= '6' &&
537 byte_digits == 0) || ('0' <= *kbinput &&
538 *kbinput <= '9' && byte_digits > 0)) {
539 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000540
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000541 byte_digits++;
542 byte = get_byte_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000543#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000544 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000545#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000546 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000547
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000548 if (byte != ERR) {
549 char *byte_mb = charalloc(mb_cur_max());
550 int byte_mb_len, *seq, i;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000551
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000552 /* If we've read in a complete byte
553 * sequence, reset the byte sequence counter
554 * and the escape counter, and put back the
555 * corresponding byte value. */
556 byte_digits = 0;
557 escapes = 0;
558
559 /* Put back the multibyte equivalent of the
560 * byte value. */
561 byte_mb = make_mbchar(byte, byte_mb,
562 &byte_mb_len);
563
564 seq = (int *)nmalloc(byte_mb_len *
565 sizeof(int));
566
567 for (i = 0; i < byte_mb_len; i++)
568 seq[i] = (unsigned char)byte_mb[i];
569
570 unget_input(seq, byte_mb_len);
571
572 free(seq);
573 free(byte_mb);
574 }
575 } else {
576 /* Reset the escape counter. */
577 escapes = 0;
578 if (byte_digits == 0)
579 /* Two escapes followed by a non-decimal
580 * digit or a decimal digit that would
581 * create a byte sequence greater than 2XX,
582 * and we're not in the middle of a byte
583 * sequence: control character sequence
584 * mode. Interpret the control sequence and
585 * save the corresponding control character
586 * as the result. */
587 retval = get_control_kbinput(*kbinput);
588 else {
589 /* If we're in the middle of a byte
590 * sequence, reset the byte sequence counter
591 * and save the character we got as the
592 * result. */
593 byte_digits = 0;
594 retval = *kbinput;
595 }
596 }
597 break;
598 }
599 }
600
601 /* If we have a result and it's an extended keypad value (i.e, a
602 * value outside of byte range), set func_key to TRUE. */
603 if (retval != ERR)
604 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000605
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000606#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000607 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 +0000608#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000609
610 /* Return the result. */
611 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000612}
613
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000614/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000615 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000616 * are generated when the keypad doesn't support the needed keys. If
617 * the escape sequence is recognized but we want to ignore it, return
618 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
619 * set ignore_seq to FALSE. Assume that Escape has already been read
620 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000621int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000622 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000623{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000624 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000625
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000626 *ignore_seq = FALSE;
627
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000628 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000629 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000630 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000631 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000632 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000633 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000634 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000635 case 'P': /* Esc O 2 P == F13 on
636 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000637 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000638 break;
639 case 'Q': /* Esc O 2 Q == F14 on
640 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000641 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000642 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000643 case 'R': /* Esc O 2 R == F15 on
644 * xterm. */
645 retval = KEY_F(15);
646 break;
647 case 'S': /* Esc O 2 S == F16 on
648 * xterm. */
649 retval = KEY_F(16);
650 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000651 }
652 }
653 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000654 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
655 case 'B': /* Esc O B == Down on
656 * VT100/VT320/xterm. */
657 case 'C': /* Esc O C == Right on
658 * VT100/VT320/xterm. */
659 case 'D': /* Esc O D == Left on
660 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000661 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000662 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000663 case 'E': /* Esc O E == Center (5) on numeric keypad
664 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000665 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000666 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000667 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000668 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000669 break;
670 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000671 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000672 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000673 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000674 * NumLock off on VT100/VT220/VT320/xterm/
675 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000676 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000677 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000678 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000679 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000680 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000681 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000682 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000683 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000684 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000685 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000686 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000687 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000688 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000689 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000690 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000691 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000692 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000693 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000694 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000695 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000696 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000697 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000698 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000699 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000700 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000701 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000702 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000703 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000704 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000705 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000706 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000707 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000708 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000709 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000710 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000711 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000712 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000713 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000714 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000715 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000716 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000717 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000718 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000719 * NumLock off on VT100/VT220/VT320/xterm/
720 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000721 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000722 break;
723 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000724 * NumLock off on VT100/VT220/VT320/xterm/
725 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000726 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000727 break;
728 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000729 * NumLock off on VT100/VT220/VT320/xterm/
730 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000731 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000732 break;
733 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000734 * NumLock off on VT100/VT220/VT320/xterm/
735 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000736 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000737 break;
738 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000739 * with NumLock off on VT100/VT220/VT320/
740 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000741 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000742 break;
743 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000744 * NumLock off on VT100/VT220/VT320/xterm/
745 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000746 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000747 break;
748 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000749 * with NumLock off on VT100/VT220/VT320/
750 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000751 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000752 break;
753 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000754 * with NumLock off on VT100/VT220/VT320/
755 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000756 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000757 break;
758 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000759 * with NumLock off on VT100/VT220/VT320/
760 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000761 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000762 break;
763 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000764 * keypad with NumLock off on VT100/VT220/
765 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000766 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000767 break;
768 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000769 * with NumLock off on VT100/VT220/VT320/
770 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000771 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000772 break;
773 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000774 * with NumLock off on VT100/VT220/VT320/
775 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000776 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000777 break;
778 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000779 * with NumLock off on VT100/VT220/VT320/
780 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000781 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000782 break;
783 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000784 * with NumLock off on VT100/VT220/VT320/
785 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000786 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000787 break;
788 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000789 * with NumLock off on VT100/VT220/VT320/
790 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000791 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000792 break;
793 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000794 * with NumLock off on VT100/VT220/VT320/
795 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000796 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000797 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000798 }
799 break;
800 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000801 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000802 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000803 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000804 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000805 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000806 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000807 break;
808 }
809 break;
810 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000811 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000812 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000813 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000814 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000815 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
816 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000817 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000818 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000819 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
820 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000821 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000822 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000823 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
824 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000825 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000826 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000827 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
828 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000829 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000830 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000831 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
832 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000833 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000834 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000835 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000836 * VT220/VT320/Linux console/
837 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000838 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000839 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000840 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000841 * VT220/VT320/Linux console/
842 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000843 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000844 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000845 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000846 * VT220/VT320/Linux console/
847 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000848 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000849 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000850 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000851 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000852 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000853 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000854 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000855 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000856 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
857 * xterm. */
858 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
859 * xterm. */
860 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
861 * xterm. */
862 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
863 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000864 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000865 break;
866 }
867 }
868 break;
869 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000870 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000871 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000872 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
873 * xterm. */
874 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
875 * xterm. */
876 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
877 * xterm. */
878 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
879 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000880 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000881 break;
882 }
883 }
884 break;
885 }
886 }
887 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000888 default: /* Esc [ 1 ~ == Home on
889 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000890 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000891 break;
892 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000893 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000894 break;
895 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000896 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000897 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000898 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000899 * VT220/VT320/Linux console/
900 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000901 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000902 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000903 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000904 * VT220/VT320/Linux console/
905 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000906 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000907 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000908 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000909 * VT220/VT320/Linux console/
910 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000911 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000912 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000913 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000914 * VT220/VT320/Linux console/
915 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000916 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000917 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000918 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000919 * VT220/VT320/Linux console/
920 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000921 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000922 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000923 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000924 * VT220/VT320/Linux console/
925 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000926 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000927 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000928 case '8': /* Esc [ 2 8 ~ == F15 on
929 * VT220/VT320/Linux console/
930 * rxvt/Eterm. */
931 retval = KEY_F(15);
932 break;
933 case '9': /* Esc [ 2 9 ~ == F16 on
934 * VT220/VT320/Linux console/
935 * rxvt/Eterm. */
936 retval = KEY_F(16);
937 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000938 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000939 * VT220/VT320/Linux console/
940 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000941 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000942 break;
943 }
944 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000945 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000946 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
947 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000948 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000949 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000950 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000951 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000952 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000953 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000954 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
955 * Linux console/xterm; Esc [ 5 ^ ==
956 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000957 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000958 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000959 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
960 * Linux console/xterm; Esc [ 6 ^ ==
961 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000962 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000963 break;
964 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000965 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000966 break;
967 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000968 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000969 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000970 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000971 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000972 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000973 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000974 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000975 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000976 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000977 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000978 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000979 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000980 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000981 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000982 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000983 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000984 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000985 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000986 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000987 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000988 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000989 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000990 case 'E': /* Esc [ E == Center (5) on numeric keypad
991 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000992 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000993 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000994 case 'F': /* Esc [ F == End on FreeBSD
995 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000996 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000997 break;
998 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000999 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001000 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001001 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001002 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001003 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001004 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001005 break;
1006 case 'I': /* Esc [ I == PageUp on FreeBSD
1007 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001008 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001009 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001010 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001011 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001012 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001013 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001014 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001015 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001016 break;
1017 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001018 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001019 break;
1020 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001021 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001022 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001023 case 'P': /* Esc [ O P == F1 on
1024 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001025 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001026 break;
1027 case 'Q': /* Esc [ O Q == F2 on
1028 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001029 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001030 break;
1031 case 'R': /* Esc [ O R == F3 on
1032 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001033 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001034 break;
1035 case 'S': /* Esc [ O S == F4 on
1036 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001037 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001038 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001039 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001040 } else {
1041 /* Esc [ O == F3 on FreeBSD console. */
1042 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001043 }
1044 break;
1045 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001046 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001047 break;
1048 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001049 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001050 break;
1051 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001052 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001053 break;
1054 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001055 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001056 break;
1057 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001058 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001059 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001060 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001062 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001063 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001064 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001065 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001066 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001067 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001068 break;
1069 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001070 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001071 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001072 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001073 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001074 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001075 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001076 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001077 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001078 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001079 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001080 case 'c': /* Esc [ c == Shift-Right on rxvt/
1081 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001082 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001083 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001084 break;
1085 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001086 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001087 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001088 case 'A': /* Esc [ [ A == F1 on Linux
1089 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001090 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001091 break;
1092 case 'B': /* Esc [ [ B == F2 on Linux
1093 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001094 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001095 break;
1096 case 'C': /* Esc [ [ C == F3 on Linux
1097 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001098 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001099 break;
1100 case 'D': /* Esc [ [ D == F4 on Linux
1101 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001102 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001103 break;
1104 case 'E': /* Esc [ [ E == F5 on Linux
1105 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001106 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001107 break;
1108 }
1109 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001110 break;
1111 }
1112 break;
1113 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001114 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001115
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001116#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001117 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001118#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001119
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001120 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001121}
1122
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001123/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001124 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001125 * to many escape sequences. */
1126int get_escape_seq_abcd(int kbinput)
1127{
1128 switch (tolower(kbinput)) {
1129 case 'a':
1130 return NANO_PREVLINE_KEY;
1131 case 'b':
1132 return NANO_NEXTLINE_KEY;
1133 case 'c':
1134 return NANO_FORWARD_KEY;
1135 case 'd':
1136 return NANO_BACK_KEY;
1137 default:
1138 return ERR;
1139 }
1140}
1141
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001142/* Translate a byte sequence: turn a three-digit decimal number from
1143 * 000 to 255 into its corresponding byte value. */
1144int get_byte_kbinput(int kbinput
1145#ifndef NANO_SMALL
1146 , bool reset
1147#endif
1148 )
1149{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001150 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001151 int retval = ERR;
1152
1153#ifndef NANO_SMALL
1154 if (reset) {
1155 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001156 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001157 return ERR;
1158 }
1159#endif
1160
1161 /* Increment the byte digit counter. */
1162 byte_digits++;
1163
1164 switch (byte_digits) {
1165 case 1:
1166 /* One digit: reset the byte sequence holder and add the
1167 * digit we got to the 100's position of the byte sequence
1168 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001169 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001170 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001171 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001172 else
1173 /* If the character we got isn't a decimal digit, or if
1174 * it is and it would put the byte sequence out of byte
1175 * range, save it as the result. */
1176 retval = kbinput;
1177 break;
1178 case 2:
1179 /* Two digits: add the digit we got to the 10's position of
1180 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001181 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1182 '6' <= kbinput && kbinput <= '9'))
1183 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001184 else
1185 /* If the character we got isn't a decimal digit, or if
1186 * it is and it would put the byte sequence out of byte
1187 * range, save it as the result. */
1188 retval = kbinput;
1189 break;
1190 case 3:
1191 /* Three digits: add the digit we got to the 1's position of
1192 * the byte sequence holder, and save the corresponding word
1193 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001194 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1195 '6' <= kbinput && kbinput <= '9')) {
1196 byte += (kbinput - '0');
1197 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001198 } else
1199 /* If the character we got isn't a decimal digit, or if
1200 * it is and it would put the word sequence out of word
1201 * range, save it as the result. */
1202 retval = kbinput;
1203 break;
1204 default:
1205 /* More than three digits: save the character we got as the
1206 * result. */
1207 retval = kbinput;
1208 break;
1209 }
1210
1211 /* If we have a result, reset the byte digit counter and the byte
1212 * sequence holder. */
1213 if (retval != ERR) {
1214 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001215 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001216 }
1217
1218#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001219 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 +00001220#endif
1221
1222 return retval;
1223}
1224
1225/* Translate a word sequence: turn a four-digit hexadecimal number from
1226 * 0000 to ffff (case-insensitive) into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001227int get_word_kbinput(int kbinput
1228#ifndef NANO_SMALL
1229 , bool reset
1230#endif
1231 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001232{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001233 static int word_digits = 0, word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001234 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001235
1236#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001237 if (reset) {
1238 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001239 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001240 return ERR;
1241 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001242#endif
1243
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001244 /* Increment the word digit counter. */
1245 word_digits++;
1246
1247 switch (word_digits) {
1248 case 1:
1249 /* One digit: reset the word sequence holder and add the
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001250 * digit we got to the 4096's position of the word sequence
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001251 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001252 word = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001253 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001254 word += (kbinput - '0') * 4096;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001255 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001256 word += (tolower(kbinput) + 10 - 'a') * 4096;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001257 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001258 /* If the character we got isn't a hexadecimal digit, or
1259 * if it is and it would put the word sequence out of
1260 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001261 retval = kbinput;
1262 break;
1263 case 2:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001264 /* Two digits: add the digit we got to the 256's position of
1265 * the word sequence holder. */
1266 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001267 word += (kbinput - '0') * 256;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001268 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001269 word += (tolower(kbinput) + 10 - 'a') * 256;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001270 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001271 /* If the character we got isn't a hexadecimal digit, or
1272 * if it is and it would put the word sequence out of
1273 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001274 retval = kbinput;
1275 break;
1276 case 3:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001277 /* Three digits: add the digit we got to the 16's position
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001278 * of the word sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001279 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001280 word += (kbinput - '0') * 16;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001281 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001282 word += (tolower(kbinput) + 10 - 'a') * 16;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001283 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001284 /* If the character we got isn't a hexadecimal digit, or
1285 * if it is and it would put the word sequence out of
1286 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001287 retval = kbinput;
1288 break;
1289 case 4:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001290 /* Four digits: add the digit we got to the 1's position of
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001291 * the word sequence holder, and save the corresponding word
1292 * value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001293 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001294 word += (kbinput - '0');
1295 retval = word;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001296 } else if ('a' <= tolower(kbinput) &&
1297 tolower(kbinput) <= 'f') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001298 word += (tolower(kbinput) + 10 - 'a');
1299 retval = word;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001300 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001301 /* If the character we got isn't a hexadecimal digit, or
1302 * if it is and it would put the word sequence out of
1303 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001304 retval = kbinput;
1305 break;
1306 default:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001307 /* More than four digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001308 * result. */
1309 retval = kbinput;
1310 break;
1311 }
1312
1313 /* If we have a result, reset the word digit counter and the word
1314 * sequence holder. */
1315 if (retval != ERR) {
1316 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001317 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001318 }
1319
1320#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001321 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 +00001322#endif
1323
1324 return retval;
1325}
1326
1327/* Translate a control character sequence: turn an ASCII non-control
1328 * character into its corresponding control character. */
1329int get_control_kbinput(int kbinput)
1330{
1331 int retval;
1332
1333 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1334 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1335 kbinput == '`')
1336 retval = NANO_CONTROL_SPACE;
1337 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1338 else if ('3' <= kbinput && kbinput <= '7')
1339 retval = kbinput - 24;
1340 /* Ctrl-8 (Ctrl-?) */
1341 else if (kbinput == '8' || kbinput == '?')
1342 retval = NANO_CONTROL_8;
1343 /* Ctrl-A to Ctrl-_ */
1344 else if ('A' <= kbinput && kbinput <= '_')
1345 retval = kbinput - 64;
1346 /* Ctrl-a to Ctrl-~ */
1347 else if ('a' <= kbinput && kbinput <= '~')
1348 retval = kbinput - 96;
1349 else
1350 retval = kbinput;
1351
1352#ifdef DEBUG
1353 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1354#endif
1355
1356 return retval;
1357}
1358
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001359/* Put the output-formatted characters in output back into the default
1360 * keystroke buffer, so that they can be parsed and displayed as output
1361 * again. */
1362void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001363{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001364 int *input;
1365 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001366
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001367 if (output_len == 0)
1368 return;
1369
1370 input = (int *)nmalloc(output_len * sizeof(int));
1371 for (i = 0; i < output_len; i++)
1372 input[i] = (int)output[i];
1373 unget_input(input, output_len);
1374 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001375}
1376
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001377/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001378 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1379int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1380{
1381 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001382
1383 /* Turn off flow control characters if necessary so that we can type
1384 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001385 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001386 if (ISSET(PRESERVE))
1387 disable_flow_control();
1388 keypad(win, FALSE);
1389
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001390 /* Read in a stream of characters and interpret it if possible. */
1391 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001392
1393 /* Turn flow control characters back on if necessary and turn the
1394 * keypad back on now that we're done. */
1395 if (ISSET(PRESERVE))
1396 enable_flow_control();
1397 keypad(win, TRUE);
1398
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001399 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001400}
1401
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001402/* Read in a stream of all available characters, and return the length
1403 * of the string in kbinput_len. Translate the first few characters of
1404 * the input into the corresponding word value if possible. After that,
1405 * leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001406int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001407{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001408 int *kbinput, word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001409
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001410 /* Read in the first keystroke. */
1411 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001412
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001413 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001414 word = get_word_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001415#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001416 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001417#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001418 );
1419
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001420 /* If the first keystroke isn't a hexadecimal digit, put back the
1421 * first keystroke. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001422 if (word != ERR)
1423 unget_input(kbinput, 1);
1424 /* Otherwise, read in keystrokes until we have a complete word
1425 * sequence, and put back the corresponding word value. */
1426 else {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001427 char *word_mb = charalloc(mb_cur_max());
1428 int word_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001429
1430 while (word == ERR) {
1431 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001432
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001433 word = get_word_kbinput(*kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001434#ifndef NANO_SMALL
1435 , FALSE
1436#endif
1437 );
1438 }
1439
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001440 /* Put back the multibyte equivalent of the word value. */
1441 word_mb = make_mbchar(word, word_mb, &word_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001442
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001443 seq = (int *)nmalloc(word_mb_len * sizeof(int));
1444
1445 for (i = 0; i < word_mb_len; i++)
1446 seq[i] = (unsigned char)word_mb[i];
1447
1448 unget_input(seq, word_mb_len);
1449
1450 free(seq);
1451 free(word_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001452 }
1453
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001454 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001455 * result. */
1456 *kbinput_len = get_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001457 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001458
1459 return retval;
1460}
1461
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001462#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001463/* Check for a mouse event, and if one's taken place, save the
1464 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001465 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1466 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001467 * place on it, figure out which shortcut was clicked and put back the
1468 * equivalent keystroke(s). Return FALSE if no keystrokes were
1469 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001470 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001471bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001472{
1473 MEVENT mevent;
1474
1475 *mouse_x = -1;
1476 *mouse_y = -1;
1477
1478 /* First, get the actual mouse event. */
1479 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001480 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001481
1482 /* Save the screen coordinates where the mouse event took place. */
1483 *mouse_x = mevent.x;
1484 *mouse_y = mevent.y;
1485
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001486 /* If we're allowing shortcuts, the current shortcut list is being
1487 * displayed on the last two lines of the screen, and the mouse
1488 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001489 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001490 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1491 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001492 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001493 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001494 /* The number of shortcuts in the current shortcut list. */
1495 const shortcut *s = currshortcut;
1496 /* The actual shortcut we clicked on, starting at the first
1497 * one in the current shortcut list. */
1498
1499 /* Get the shortcut lists' length. */
1500 if (currshortcut == main_list)
1501 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001502 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001503 currslen = length_of_list(currshortcut);
1504
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001505 /* We don't show any more shortcuts than the main list
1506 * does. */
1507 if (currslen > MAIN_VISIBLE)
1508 currslen = MAIN_VISIBLE;
1509 }
1510
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001511 /* Calculate the width of each shortcut in the list (it's the
1512 * same for all of them). */
1513 if (currslen < 2)
1514 i = COLS / 6;
1515 else
1516 i = COLS / ((currslen / 2) + (currslen % 2));
1517
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001518 /* Calculate the y-coordinate relative to the beginning of
1519 * bottomwin. */
1520 j = *mouse_y - ((2 - no_more_space()) + 1) - editwinrows;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001521
1522 /* If we're on the statusbar, beyond the end of the shortcut
1523 * list, or beyond the end of a shortcut on the right side of
1524 * the screen, don't do anything. */
1525 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001526 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001527 j = (*mouse_x / i) * 2 + j;
1528 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001529 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001530
1531 /* Go through the shortcut list to determine which shortcut was
1532 * clicked. */
1533 for (; j > 0; j--)
1534 s = s->next;
1535
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001536 /* And put back the equivalent key. Assume that each shortcut
1537 * has, at the very least, an equivalent control key, an
1538 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001539 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001540 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001541 return TRUE;
1542 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001543 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001544 return TRUE;
1545 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001546 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001547 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001548}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001549#endif /* !DISABLE_MOUSE */
1550
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001551const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001552 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001553{
1554 const shortcut *s = s_list;
1555 size_t slen = length_of_list(s_list);
1556
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001557#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001558 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 +00001559#endif
1560
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001561 /* Check for shortcuts. */
1562 for (; slen > 0; slen--) {
1563 /* We've found a shortcut if:
1564 *
1565 * 1. The key exists.
1566 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001567 * 3. meta_key is TRUE and the key is the primary or
1568 * miscellaneous meta sequence in the shortcut list.
1569 * 4. func_key is TRUE and the key is a function key in the
1570 * shortcut list. */
1571
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001572 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1573 (*meta_key == TRUE && (*kbinput == s->metaval ||
1574 *kbinput == s->miscval)) || (*func_key == TRUE &&
1575 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001576 break;
1577 }
1578
1579 s = s->next;
1580 }
1581
1582 /* Translate the shortcut to either its control key or its meta key
1583 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001584 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001585 if (slen > 0) {
1586 if (s->ctrlval != NANO_NO_KEY) {
1587 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001588 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001589 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001590 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001591 } else if (s->metaval != NANO_NO_KEY) {
1592 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001593 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001594 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001595 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001596 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001597 }
1598
1599 return NULL;
1600}
1601
1602#ifndef NANO_SMALL
1603const toggle *get_toggle(int kbinput, bool meta_key)
1604{
1605 const toggle *t = toggles;
1606
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001607#ifdef DEBUG
1608 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1609#endif
1610
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001611 /* Check for toggles. */
1612 for (; t != NULL; t = t->next) {
1613 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001614 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001615 if (meta_key && kbinput == t->val)
1616 break;
1617 }
1618
1619 return t;
1620}
1621#endif /* !NANO_SMALL */
1622
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001623int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001624 bool *ran_func, bool *finished, bool allow_funcs)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001625{
1626 int input;
1627 /* The character we read in. */
1628 static int *kbinput = NULL;
1629 /* The input buffer. */
1630 static size_t kbinput_len = 0;
1631 /* The length of the input buffer. */
1632 const shortcut *s;
1633 bool have_shortcut;
1634
1635 *s_or_t = FALSE;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001636 *ran_func = FALSE;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001637 *finished = FALSE;
1638
1639 /* Read in a character. */
1640 input = get_kbinput(bottomwin, meta_key, func_key);
1641
1642#ifndef DISABLE_MOUSE
1643 /* If we got a mouse click and it was on a shortcut, read in the
1644 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001645 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001646 if (do_mouse())
1647 input = get_kbinput(bottomwin, meta_key, func_key);
1648 else
1649 input = ERR;
1650 }
1651#endif
1652
1653 /* Check for a shortcut in the current list. */
1654 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1655
1656 /* If we got a shortcut from the current list, or a "universal"
1657 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1658 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1659 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1660 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1661 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001662 input == NANO_CUT_KEY ||
1663#ifndef NANO_SMALL
1664 input == NANO_NEXTWORD_KEY ||
1665#endif
1666 (*meta_key == TRUE && (
1667#ifndef NANO_SMALL
1668 input == NANO_PREVWORD_KEY ||
1669#endif
1670 input == NANO_VERBATIM_KEY)));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001671
1672 /* Set s_or_t to TRUE if we got a shortcut. */
1673 *s_or_t = have_shortcut;
1674
1675 if (allow_funcs) {
1676 if (input != ERR && *s_or_t == FALSE && !is_cntrl_char(input)) {
1677 /* If we're using restricted mode, the filename isn't blank,
1678 * and we're at the "Write File" prompt, disable text
1679 * input. */
1680 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1681 currshortcut != writefile_list) {
1682 kbinput_len++;
1683 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1684 sizeof(int));
1685 kbinput[kbinput_len - 1] = input;
1686 }
1687 }
1688
1689 /* If we got a shortcut, or if there aren't any other characters
1690 * waiting after the one we read in, we need to display all the
1691 * characters in the input buffer if it isn't empty. */
1692 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1693 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001694
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001695 /* Display all the characters in the input buffer at
1696 * once. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001697 char *output = charalloc(kbinput_len + 1);
1698 size_t i;
1699 bool got_enter;
1700 /* Whether we got the Enter key. */
1701
1702 for (i = 0; i < kbinput_len; i++)
1703 output[i] = (char)kbinput[i];
1704 output[i] = '\0';
1705
1706 do_statusbar_output(output, kbinput_len, &got_enter);
1707
1708 free(output);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001709
1710 /* Empty the input buffer. */
1711 kbinput_len = 0;
1712 free(kbinput);
1713 kbinput = NULL;
1714 }
1715 }
1716
1717 if (have_shortcut) {
1718 switch (input) {
1719 /* Handle the "universal" statusbar prompt shortcuts. */
1720 case NANO_REFRESH_KEY:
1721 total_refresh();
1722 break;
1723 case NANO_HOME_KEY:
1724 do_statusbar_home();
1725 break;
1726 case NANO_END_KEY:
1727 do_statusbar_end();
1728 break;
1729 case NANO_FORWARD_KEY:
1730 do_statusbar_right();
1731 break;
1732 case NANO_BACK_KEY:
1733 do_statusbar_left();
1734 break;
1735 case NANO_BACKSPACE_KEY:
1736 /* If we're using restricted mode, the filename
1737 * isn't blank, and we're at the "Write File"
1738 * prompt, disable Backspace. */
1739 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1740 currshortcut != writefile_list)
1741 do_statusbar_backspace();
1742 break;
1743 case NANO_DELETE_KEY:
1744 /* If we're using restricted mode, the filename
1745 * isn't blank, and we're at the "Write File"
1746 * prompt, disable Delete. */
1747 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1748 currshortcut != writefile_list)
1749 do_statusbar_delete();
1750 break;
1751 case NANO_CUT_KEY:
1752 /* If we're using restricted mode, the filename
1753 * isn't blank, and we're at the "Write File"
1754 * prompt, disable Cut. */
1755 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1756 currshortcut != writefile_list)
1757 do_statusbar_cut_text();
1758 break;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001759#ifndef NANO_SMALL
1760 case NANO_NEXTWORD_KEY:
1761 do_statusbar_next_word();
1762 break;
1763 case NANO_PREVWORD_KEY:
1764 if (*meta_key == TRUE)
1765 do_statusbar_prev_word();
1766 break;
1767#endif
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001768 case NANO_VERBATIM_KEY:
1769 if (*meta_key == TRUE) {
1770 /* If we're using restricted mode, the filename
1771 * isn't blank, and we're at the "Write File"
1772 * prompt, disable verbatim input. */
1773 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001774 currshortcut != writefile_list) {
1775 bool got_enter;
1776 /* Whether we got the Enter key. */
1777
1778 do_statusbar_verbatim_input(&got_enter);
1779
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001780 /* If we got the Enter key, set input to the
1781 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001782 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001783 if (got_enter) {
1784 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001785 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001786 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001787 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001788 break;
1789 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001790 /* Handle the normal statusbar prompt shortcuts, setting
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001791 * ran_func to TRUE if we try to run their associated
1792 * functions and setting finished to TRUE to indicate
1793 * that we're done after trying to run their associated
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001794 * functions. */
1795 default:
1796 if (s->func != NULL) {
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001797 *ran_func = TRUE;
1798 if (!ISSET(VIEW_MODE) || s->viewok)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001799 s->func();
1800 }
1801 *finished = TRUE;
1802 }
1803 }
1804 }
1805
1806 return input;
1807}
1808
1809#ifndef DISABLE_MOUSE
1810bool do_statusbar_mouse(void)
1811{
1812 /* FIXME: If we clicked on a location in the statusbar, the cursor
1813 * should move to the location we clicked on. This functionality
1814 * should be in this function. */
1815 int mouse_x, mouse_y;
1816 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1817}
1818#endif
1819
1820void do_statusbar_home(void)
1821{
1822#ifndef NANO_SMALL
1823 if (ISSET(SMART_HOME)) {
1824 size_t statusbar_x_save = statusbar_x;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001825
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001826 statusbar_x = indent_length(answer);
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001827
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001828 if (statusbar_x == statusbar_x_save ||
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001829 statusbar_x == strlen(answer))
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001830 statusbar_x = 0;
1831 } else
1832#endif
1833 statusbar_x = 0;
1834}
1835
1836void do_statusbar_end(void)
1837{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001838 statusbar_x = strlen(answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001839}
1840
1841void do_statusbar_right(void)
1842{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001843 if (statusbar_x < strlen(answer))
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001844 statusbar_x = move_mbright(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001845}
1846
1847void do_statusbar_left(void)
1848{
1849 if (statusbar_x > 0)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001850 statusbar_x = move_mbleft(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001851}
1852
1853void do_statusbar_backspace(void)
1854{
1855 if (statusbar_x > 0) {
1856 do_statusbar_left();
1857 do_statusbar_delete();
1858 }
1859}
1860
1861void do_statusbar_delete(void)
1862{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001863 if (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001864 int char_buf_len = parse_mbchar(answer + statusbar_x, NULL,
1865 NULL, NULL);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001866 size_t line_len = strlen(answer + statusbar_x);
1867
1868 assert(statusbar_x < strlen(answer));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001869
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001870 charmove(answer + statusbar_x, answer + statusbar_x +
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001871 char_buf_len, strlen(answer) - statusbar_x -
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001872 char_buf_len + 1);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001873
1874 null_at(&answer, statusbar_x + line_len - char_buf_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001875 }
1876}
1877
1878void do_statusbar_cut_text(void)
1879{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001880 assert(answer != NULL);
1881
1882 if (ISSET(CUT_TO_END))
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001883 null_at(&answer, statusbar_x);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001884 else {
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001885 null_at(&answer, 0);
1886 statusbar_x = 0;
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001887 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001888}
1889
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001890#ifndef NANO_SMALL
1891void do_statusbar_next_word(void)
1892{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001893 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001894 int char_mb_len;
1895
1896 assert(answer != NULL);
1897
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001898 char_mb = charalloc(mb_cur_max());
1899
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001900 /* Move forward until we find the character after the last letter of
1901 * the current word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001902 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001903 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1904 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001905
1906 /* If we've found it, stop moving forward through the current
1907 * line. */
1908 if (!is_alnum_mbchar(char_mb))
1909 break;
1910
1911 statusbar_x += char_mb_len;
1912 }
1913
1914 /* Move forward until we find the first letter of the next word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001915 if (answer[statusbar_x] != '\0')
1916 statusbar_x += char_mb_len;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001917
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001918 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001919 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1920 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001921
1922 /* If we've found it, stop moving forward through the current
1923 * line. */
1924 if (is_alnum_mbchar(char_mb))
1925 break;
1926
1927 statusbar_x += char_mb_len;
1928 }
1929
1930 free(char_mb);
1931}
1932
1933void do_statusbar_prev_word(void)
1934{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001935 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001936 int char_mb_len;
1937 bool begin_line = FALSE;
1938
1939 assert(answer != NULL);
1940
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001941 char_mb = charalloc(mb_cur_max());
1942
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001943 /* Move backward until we find the character before the first letter
1944 * of the current word. */
1945 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001946 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1947 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001948
1949 /* If we've found it, stop moving backward through the current
1950 * line. */
1951 if (!is_alnum_mbchar(char_mb))
1952 break;
1953
1954 if (statusbar_x == 0)
1955 begin_line = TRUE;
1956 else
1957 statusbar_x = move_mbleft(answer, statusbar_x);
1958 }
1959
1960 /* Move backward until we find the last letter of the previous
1961 * word. */
1962 if (statusbar_x == 0)
1963 begin_line = TRUE;
1964 else
1965 statusbar_x = move_mbleft(answer, statusbar_x);
1966
1967 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001968 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1969 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001970
1971 /* If we've found it, stop moving backward through the current
1972 * line. */
1973 if (is_alnum_mbchar(char_mb))
1974 break;
1975
1976 if (statusbar_x == 0)
1977 begin_line = TRUE;
1978 else
1979 statusbar_x = move_mbleft(answer, statusbar_x);
1980 }
1981
1982 /* If we've found it, move backward until we find the character
1983 * before the first letter of the previous word. */
1984 if (!begin_line) {
1985 if (statusbar_x == 0)
1986 begin_line = TRUE;
1987 else
1988 statusbar_x = move_mbleft(answer, statusbar_x);
1989
1990 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001991 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
1992 NULL, NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001993
1994 /* If we've found it, stop moving backward through the
1995 * current line. */
1996 if (!is_alnum_mbchar(char_mb))
1997 break;
1998
1999 if (statusbar_x == 0)
2000 begin_line = TRUE;
2001 else
2002 statusbar_x = move_mbleft(answer, statusbar_x);
2003 }
2004
2005 /* If we've found it, move forward to the first letter of the
2006 * previous word. */
2007 if (!begin_line)
2008 statusbar_x += char_mb_len;
2009 }
2010
2011 free(char_mb);
2012}
2013#endif
2014
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002015void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002016{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002017 int *kbinput;
2018 size_t kbinput_len, i;
2019 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002020
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002021 *got_enter = FALSE;
2022
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002023 /* Read in all the verbatim characters. */
2024 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
2025
2026 /* Display all the verbatim characters at once. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002027 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002028
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002029 for (i = 0; i < kbinput_len; i++)
2030 output[i] = (char)kbinput[i];
2031 output[i] = '\0';
2032
2033 do_statusbar_output(output, kbinput_len, got_enter);
2034
2035 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002036}
2037
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002038void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002039 *got_enter)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002040{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002041 size_t answer_len = strlen(answer), i = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002042 char *char_buf = charalloc(mb_cur_max());
2043 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002044
2045 assert(answer != NULL);
2046
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002047 *got_enter = FALSE;
2048
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002049 while (i < output_len) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002050 /* Null to newline, if needed. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002051 if (output[i] == '\0')
2052 output[i] = '\n';
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002053 /* Newline to Enter, if needed. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002054 else if (output[i] == '\n') {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002055 /* Set got_enter to TRUE to indicate that we got the Enter
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002056 * key, put back the rest of the characters in output so
2057 * that they can be parsed and output again, and get out. */
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002058 *got_enter = TRUE;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002059 unparse_kbinput(output + i, output_len - i);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002060 return;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002061 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002062
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002063 /* Interpret the next multibyte character. If it's an invalid
2064 * multibyte character, interpret it as though it's a byte
2065 * character. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002066 char_buf_len = parse_mbchar(output + i, char_buf, NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002067
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002068 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002069
2070 /* More dangerousness fun =) */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002071 answer = charealloc(answer, answer_len + (char_buf_len * 2));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002072
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002073 assert(statusbar_x <= answer_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002074
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002075 charmove(&answer[statusbar_x + char_buf_len],
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002076 &answer[statusbar_x], answer_len - statusbar_x +
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002077 char_buf_len);
2078 charcpy(&answer[statusbar_x], char_buf, char_buf_len);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002079 answer_len += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002080
2081 do_statusbar_right();
2082 }
2083
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002084 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002085}
2086
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002087/* Return the placewewant associated with current_x, i.e, the zero-based
2088 * column position of the cursor. The value will be no smaller than
2089 * current_x. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002090size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002091{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002092 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002093}
2094
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002095/* actual_x() gives the index in str of the character displayed at
2096 * column xplus. That is, actual_x() is the largest value such that
2097 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2098size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002099{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002100 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002101 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002102 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002103 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002104
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002105 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002106
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002107 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002108 int str_len = parse_mbchar(str, NULL, NULL, &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002109
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002110 if (length > xplus)
2111 break;
2112
2113 i += str_len;
2114 str += str_len;
2115 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002116
Chris Allegretta6df90f52002-07-19 01:08:59 +00002117 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002118}
2119
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002120/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002121 * columns wide are the first size characters of str? */
2122size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002123{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002124 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002125 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002126
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002127 if (size == 0)
2128 return 0;
2129
2130 assert(str != NULL);
2131
2132 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002133 int str_len = parse_mbchar(str, NULL, NULL, &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002134
2135 str += str_len;
2136
2137 if (size <= str_len)
2138 break;
2139
2140 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002141 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002142
Chris Allegretta6df90f52002-07-19 01:08:59 +00002143 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002144}
2145
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002146/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002147size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002148{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002149 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002150}
2151
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002152void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002153{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002154 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002155}
2156
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002157void blank_topbar(void)
2158{
2159 if (!ISSET(MORE_SPACE))
2160 mvwaddstr(topwin, 1, 0, hblank);
2161}
2162
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002163void blank_edit(void)
2164{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002165 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002166 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002167 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002168}
2169
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002170void blank_statusbar(void)
2171{
2172 mvwaddstr(bottomwin, 0, 0, hblank);
2173}
2174
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002175void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002176{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002177 if (statusblank > 1)
2178 statusblank--;
2179 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
2180 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002181 blank_statusbar();
2182 wnoutrefresh(bottomwin);
2183 reset_cursor();
2184 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002185 }
2186}
2187
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002188void blank_bottombars(void)
2189{
2190 if (!ISSET(NO_HELP)) {
2191 mvwaddstr(bottomwin, 1, 0, hblank);
2192 mvwaddstr(bottomwin, 2, 0, hblank);
2193 }
2194}
2195
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002196/* Convert buf into a string that can be displayed on screen. The
2197 * caller wants to display buf starting with column start_col, and
2198 * extending for at most len columns. start_col is zero-based. len is
2199 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002200 * string is dynamically allocated, and should be freed. If dollars is
2201 * TRUE, the caller might put "$" at the beginning or end of the line if
2202 * it's too long. */
2203char *display_string(const char *buf, size_t start_col, size_t len, bool
2204 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002205{
2206 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002207 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002208 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002209 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002210 size_t alloc_len;
2211 /* The length of memory allocated for converted. */
2212 char *converted;
2213 /* The string we return. */
2214 size_t index;
2215 /* Current position in converted. */
2216
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002217 char *buf_mb = charalloc(mb_cur_max());
2218 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002219 bool bad_char;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002220
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002221 /* If dollars is TRUE, make room for the "$" at the end of the
2222 * line. */
2223 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2224 len--;
2225
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002226 if (len == 0)
2227 return mallocstrcpy(NULL, "");
2228
2229 start_index = actual_x(buf, start_col);
2230 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002231
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002232 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002233
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002234 /* Allocate enough space for the entire line. It should contain
2235 * (len + 2) multibyte characters at most. */
2236 alloc_len = mb_cur_max() * (len + 2);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002237
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002238 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002239 index = 0;
2240
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002241 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002242 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002243 /* We don't display all of buf[start_index] since it starts to
2244 * the left of the screen. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002245 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL,
2246 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002247
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002248 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002249 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002250 char *ctrl_buf_mb = charalloc(mb_cur_max());
2251 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002252
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002253 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2254 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002255
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002256 for (i = 0; i < ctrl_buf_mb_len; i++)
2257 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002258
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002259 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002260
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002261 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002262
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002263 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002264 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002265 }
2266#ifdef NANO_WIDE
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002267 else if (mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002268 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002269 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002270
2271 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002272 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002273#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002274 }
2275
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002276 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseybc149412005-02-11 20:23:00 +00002277 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, &bad_char,
2278 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002279
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002280 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002281 converted[index++] =
2282#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2283 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
2284#endif
2285 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002286 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002287 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002288 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002289 start_col++;
2290 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002291 /* If buf contains a control character, interpret it. If it
2292 * contains an invalid multibyte control character, interpret
2293 * that character as though it's a normal control character. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002294 } else if (is_cntrl_mbchar(buf_mb)) {
2295 char *ctrl_buf_mb = charalloc(mb_cur_max());
2296 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002297
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002298 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002299 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002300
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002301 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2302 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002303
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002304 for (i = 0; i < ctrl_buf_mb_len; i++)
2305 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002306
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002307 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002308
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002309 free(ctrl_buf_mb);
2310 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002311 converted[index++] =
2312#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2313 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
2314#endif
2315 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002316 start_col++;
2317 } else {
2318 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002319
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002320#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002321 /* If buf contains an invalid multibyte non-control
2322 * character, interpret that character as though it's a
2323 * normal non-control character. */
2324 if (!ISSET(NO_UTF8) && bad_char) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002325 char *bad_buf_mb = charalloc(mb_cur_max());
2326 int bad_buf_mb_len;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002327
David Lawrence Ramsey4c6956b2005-01-12 04:32:43 +00002328 bad_buf_mb = make_mbchar((unsigned char)*buf_mb,
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002329 bad_buf_mb, &bad_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002330
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002331 for (i = 0; i < bad_buf_mb_len; i++)
2332 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002333
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002334 start_col += mbwidth(bad_buf_mb);
2335
2336 free(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002337 } else {
2338#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002339 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002340 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002341
2342 start_col += mbwidth(buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002343#ifdef NANO_WIDE
2344 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002345#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002346 }
2347
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002348 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002349 }
2350
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002351 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002352 converted[index] = '\0';
2353
2354 /* Make sure converted takes up no more than len columns. */
2355 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002356 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002357
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002358 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002359}
2360
Chris Allegretta7662c862003-01-13 01:35:15 +00002361/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002362 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002363 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002364 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002365 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002366void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002367{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002368 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002369 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002370
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002371 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002372
Chris Allegrettab3655b42001-10-22 03:15:31 +00002373 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002374 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002375
Chris Allegretta6df90f52002-07-19 01:08:59 +00002376 mvwaddstr(bottomwin, 0, 0, buf);
2377 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002378
2379 if (COLS > 1)
2380 waddch(bottomwin, x_real < wid ? ' ' : '$');
2381 if (COLS > 2) {
2382 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002383 char *expanded = display_string(inputbuf, page_start, wid,
2384 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002385
2386 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002387 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002388
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002389 waddstr(bottomwin, expanded);
2390 free(expanded);
2391 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2392 } else
2393 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002394 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002395}
2396
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002397/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002398 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002399int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002400#ifndef NANO_SMALL
2401 historyheadtype *history_list,
2402#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002403 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002404#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002405 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002406#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002407 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002408{
2409 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002410 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002411 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002412 /* used by input_tab() */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002413 size_t answer_len = strlen(def);
Chris Allegretta598106e2002-01-19 01:59:37 +00002414
Chris Allegretta5beed502003-01-05 20:41:21 +00002415#ifndef NANO_SMALL
2416 /* for history */
2417 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00002418 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00002419 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002420 int last_kbinput = 0;
2421
2422 /* This variable is used in the search history code. use_cb == 0
2423 means that we're using the existing history and ignoring
2424 currentbuf. use_cb == 1 means that the entry in answer should be
2425 moved to currentbuf or restored from currentbuf to answer.
2426 use_cb == 2 means that the entry in currentbuf should be moved to
2427 answer or restored from answer to currentbuf. */
2428 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002429#endif
Chris Allegretta09fc4302003-01-16 22:16:38 +00002430
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002431 /* Only put statusbar_x at the end of the string if it's
2432 * uninitialized, if it would be past the end of the string as it
2433 * is, or if resetstatuspos is TRUE. Otherwise, leave it alone.
2434 * This is so the cursor position stays at the same place if a
2435 * prompt-changing toggle is pressed. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002436 if (statusbar_x == (size_t)-1 || statusbar_x > answer_len ||
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002437 resetstatuspos)
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002438 statusbar_x = answer_len;
Chris Allegretta09fc4302003-01-16 22:16:38 +00002439
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002440 answer = charealloc(answer, answer_len + 1);
2441 if (answer_len > 0)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002442 strcpy(answer, def);
2443 else
2444 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002445
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002446 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002447
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002448 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00002449
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002450 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002451
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002452 /* Refresh the edit window before getting input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002453 wnoutrefresh(edit);
2454 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002455
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002456 /* If we're using restricted mode, we aren't allowed to change the
2457 * name of a file once it has one because that would allow writing
2458 * to files not specified on the command line. In this case,
2459 * disable all keys that would change the text if the filename isn't
2460 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002461 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002462 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002463 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002464
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002465 /* If we have a shortcut with an associated function, break out
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002466 * if we're finished after running or trying to run the
2467 * function. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002468 if (finished)
2469 break;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002470
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002471 assert(statusbar_x <= answer_len && answer_len == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002472
Chris Allegretta04d848e2000-11-05 17:54:41 +00002473 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002474 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00002475
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002476 switch (kbinput) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002477 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002478#ifndef NANO_SMALL
2479 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00002480 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002481 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002482 history_list->current = (historytype *)history_list;
2483 history_list->len = strlen(answer);
2484 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002485
Chris Allegretta7662c862003-01-13 01:35:15 +00002486 if (history_list->len > 0) {
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002487 complete = get_history_completion(history_list,
2488 answer);
Chris Allegretta5beed502003-01-05 20:41:21 +00002489 answer = mallocstrcpy(answer, complete);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002490 answer_len = strlen(answer);
2491 statusbar_x = answer_len;
Chris Allegretta5beed502003-01-05 20:41:21 +00002492 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002493 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002494#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002495 else
2496#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002497#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002498#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002499 if (allow_tabs) {
David Lawrence Ramsey65e6ecb2005-02-08 20:37:53 +00002500 answer = input_tab(answer, &statusbar_x, &tabbed, list);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002501 answer_len = strlen(answer);
Chris Allegretta5beed502003-01-05 20:41:21 +00002502 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002503 break;
David Lawrence Ramsey65e6ecb2005-02-08 20:37:53 +00002504#endif
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002505 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002506#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002507 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002508
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002509 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2510 isn't NULL, and currentbuf is different from answer,
2511 it means that we're scrolling up at the top of the
2512 search history, and we need to save the current
2513 answer in currentbuf; do this and reset use_cb to
2514 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002515 if (currentbuf == NULL || (use_cb == 1 &&
2516 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002517 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002518 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002519 }
2520
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002521 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2522 is different from answer, it means that we're
2523 scrolling up at the bottom of the search history, and
2524 we need to make the string in currentbuf the current
2525 answer; do this, blow away currentbuf since we don't
2526 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002527 if (currentbuf != NULL && use_cb == 2 &&
2528 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002529 answer = mallocstrcpy(answer, currentbuf);
2530 free(currentbuf);
2531 currentbuf = NULL;
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002532 answer_len = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002533 use_cb = 0;
2534
2535 /* else get older search from the history list and save
2536 it in answer; if there is no older search, blank out
2537 answer */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002538 } else if ((history =
2539 get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002540 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002541 answer_len = strlen(history);
Chris Allegretta5beed502003-01-05 20:41:21 +00002542 } else {
2543 answer = mallocstrcpy(answer, "");
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002544 answer_len = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002545 }
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002546 statusbar_x = answer_len;
Chris Allegretta5beed502003-01-05 20:41:21 +00002547 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002548#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002549 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002550 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002551#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002552 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002553
2554 /* get newer search from the history list and save it
2555 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002556 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002557 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002558 answer_len = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002559
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002560 /* if there is no newer search, we're here */
2561
2562 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2563 that we're scrolling down at the bottom of the search
2564 history and we need to make the string in currentbuf
2565 the current answer; do this, blow away currentbuf
2566 since we don't need it anymore, and set use_cb to
2567 1 */
2568 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002569 answer = mallocstrcpy(answer, currentbuf);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002570 answer_len = strlen(answer);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002571 free(currentbuf);
2572 currentbuf = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002573 use_cb = 1;
2574
2575 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2576 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002577 the search history and the current answer (if it's
2578 not blank) needs to be saved in currentbuf; do this,
2579 blank out answer (if necessary), and set use_cb to
2580 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002581 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002582 if (answer[0] != '\0') {
2583 currentbuf = mallocstrcpy(currentbuf, answer);
2584 answer = mallocstrcpy(answer, "");
2585 }
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002586 answer_len = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002587 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002588 }
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002589 statusbar_x = answer_len;
Chris Allegretta5beed502003-01-05 20:41:21 +00002590 }
2591#endif
2592 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002593 }
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002594#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002595 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002596#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002597 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002598 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002599 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002600
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002601 /* We finished putting in an answer or ran a normal shortcut's
2602 * associated function, so reset statusbar_x. */
2603 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
2604 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002605 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002606
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002607 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002608}
2609
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002610/* Ask a question on the statusbar. Answer will be stored in answer
2611 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2612 * otherwise, the valid shortcut key caught. def is any editable text
2613 * we want to put up by default.
2614 *
2615 * New arg tabs tells whether or not to allow tab completion. */
2616int statusq(bool allow_tabs, const shortcut *s, const char *def,
2617#ifndef NANO_SMALL
2618 historyheadtype *which_history,
2619#endif
2620 const char *msg, ...)
2621{
2622 va_list ap;
2623 char *foo = charalloc(COLS - 3);
2624 int ret;
2625#ifndef DISABLE_TABCOMP
2626 bool list = FALSE;
2627#endif
2628
2629 bottombars(s);
2630
2631 va_start(ap, msg);
2632 vsnprintf(foo, COLS - 4, msg, ap);
2633 va_end(ap);
2634 foo[COLS - 4] = '\0';
2635
2636 ret = nanogetstr(allow_tabs, foo, def,
2637#ifndef NANO_SMALL
2638 which_history,
2639#endif
2640 s
2641#ifndef DISABLE_TABCOMP
2642 , &list
2643#endif
2644 );
2645 free(foo);
2646 resetstatuspos = FALSE;
2647
2648 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002649 case NANO_CANCEL_KEY:
2650 ret = -1;
2651 resetstatuspos = TRUE;
2652 break;
2653 case NANO_ENTER_KEY:
2654 ret = (answer[0] == '\0') ? -2 : 0;
2655 resetstatuspos = TRUE;
2656 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002657 }
2658 blank_statusbar();
2659
2660#ifdef DEBUG
2661 fprintf(stderr, "I got \"%s\"\n", answer);
2662#endif
2663
2664#ifndef DISABLE_TABCOMP
2665 /* if we've done tab completion, there might be a list of
2666 filename matches on the edit window at this point; make sure
2667 they're cleared off. */
2668 if (list)
2669 edit_refresh();
2670#endif
2671
2672 return ret;
2673}
2674
2675void statusq_abort(void)
2676{
2677 resetstatuspos = TRUE;
2678}
2679
Chris Allegrettaf717f982003-02-13 22:25:01 +00002680void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002681{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002682 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002683 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002684 size_t verlen = strlenpt(VERMSG) + 1;
2685 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002686 const char *prefix;
2687 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2688 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002689 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002690 const char *state;
2691 /* "Modified", "View", or spaces the length of "Modified".
2692 * Tells the state of this buffer. */
2693 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002694 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002695 char *exppath = NULL;
2696 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002697 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002698 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002699 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002700 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002701
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002702 assert(path != NULL || filename != NULL);
2703 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002704
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002705 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002706
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002707 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002708
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002709 if (COLS <= 5 || COLS - 5 < verlen)
2710 space = 0;
2711 else {
2712 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002713 /* Reserve 2/3 of the screen plus one column for after the
2714 * version message. */
2715 if (space < COLS - (COLS / 3) + 1)
2716 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002717 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002718
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002719 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002720 /* The version message should only take up 1/3 of the screen
2721 * minus one column. */
2722 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002723 waddstr(topwin, " ");
2724 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002725
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002726 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002727 state = _("Modified");
2728 else if (path == NULL && ISSET(VIEW_MODE))
2729 state = _("View");
2730 else {
2731 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002732 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002733 state = &hblank[COLS - statelen];
2734 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002735 statelen = strnlenpt(state, COLS);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002736 /* We need a space before state. */
2737 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2738 statelen++;
2739
2740 assert(space >= 0);
2741 if (space == 0 || statelen >= space)
2742 goto the_end;
2743
2744#ifndef DISABLE_BROWSER
2745 if (path != NULL)
2746 prefix = _("DIR:");
2747 else
2748#endif
2749 if (filename[0] == '\0') {
2750 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002751 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002752 } else
2753 prefix = _("File:");
2754 assert(statelen < space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002755 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002756 /* If newfie is FALSE, we need a space after prefix. */
2757 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002758 prefixlen++;
2759
2760 if (path == NULL)
2761 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002762 if (space >= prefixlen + statelen)
2763 space -= prefixlen + statelen;
2764 else
2765 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002766 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002767 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002768 size_t lenpt = strlenpt(path), start_col;
2769
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002770 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002771
2772 if (dots) {
2773 start_col = lenpt - space + 3;
2774 space -= 3;
2775 } else
2776 start_col = 0;
2777
2778 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002779 }
2780
2781 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002782 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2783 /* The length of the expanded filename. */
2784
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002785 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002786 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002787 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002788 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002789 assert(strlenpt(prefix) + 1 == prefixlen);
2790
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002791 waddch(topwin, ' ');
2792 waddstr(topwin, exppath);
2793 }
2794 } else {
2795 /* We will say something like "File: ...ename". */
2796 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002797 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002798 goto the_end;
2799 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002800 waddnstr(topwin, "...", space + 3);
2801 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002802 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002803 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002804 }
2805
2806 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002807 free(exppath);
2808
2809 if (COLS <= 1 || statelen >= COLS - 1)
2810 mvwaddnstr(topwin, 0, 0, state, COLS);
2811 else {
2812 assert(COLS - statelen - 2 >= 0);
2813 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2814 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2815 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002816
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002817 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002818
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002819 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002820 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002821 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002822}
2823
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002824/* If modified is not already set, set it and update titlebar. */
2825void set_modified(void)
2826{
2827 if (!ISSET(MODIFIED)) {
2828 SET(MODIFIED);
2829 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002830 }
2831}
2832
2833void statusbar(const char *msg, ...)
2834{
2835 va_list ap;
2836
2837 va_start(ap, msg);
2838
2839 /* Curses mode is turned off. If we use wmove() now, it will muck
2840 * up the terminal settings. So we just use vfprintf(). */
2841 if (curses_ended) {
2842 vfprintf(stderr, msg, ap);
2843 va_end(ap);
2844 return;
2845 }
2846
2847 /* Blank out the line. */
2848 blank_statusbar();
2849
2850 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002851 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002852 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002853#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002854 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002855
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002856 UNSET(WHITESPACE_DISPLAY);
2857#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002858 bar = charalloc(mb_cur_max() * (COLS - 3));
2859 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002860 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002861 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002862#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2863 if (old_whitespace)
2864 SET(WHITESPACE_DISPLAY);
2865#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002866 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002867 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002868 start_x = (COLS - foo_len - 4) / 2;
2869
2870 wmove(bottomwin, 0, start_x);
2871 wattron(bottomwin, A_REVERSE);
2872
2873 waddstr(bottomwin, "[ ");
2874 waddstr(bottomwin, foo);
2875 free(foo);
2876 waddstr(bottomwin, " ]");
2877 wattroff(bottomwin, A_REVERSE);
2878 wnoutrefresh(bottomwin);
2879 reset_cursor();
2880 wrefresh(edit);
2881 /* Leave the cursor at its position in the edit window, not
2882 * in the statusbar. */
2883 }
2884
2885 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002886 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002887}
2888
Chris Allegretta6232d662002-05-12 19:52:15 +00002889void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002890{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002891 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002892
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002893 if (ISSET(NO_HELP))
2894 return;
2895
Chris Allegretta6232d662002-05-12 19:52:15 +00002896 if (s == main_list) {
2897 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002898 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002899 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002900 slen = length_of_list(s);
2901
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002902 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002903 if (slen > MAIN_VISIBLE)
2904 slen = MAIN_VISIBLE;
2905 }
2906
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002907 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002908 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002909 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002910
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002911 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002912
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002913 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002914 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002915
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002916 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002917#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002918 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002919 keystr = _("Up");
2920 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002921#endif
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00002922 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002923
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002924 if (s->ctrlval == NANO_CONTROL_SPACE)
2925 strcpy(foo, "^ ");
2926 else if (s->ctrlval == NANO_CONTROL_8)
2927 strcpy(foo, "^?");
2928 /* Normal values. Assume that the shortcut has an
2929 * equivalent control key, meta key sequence, or both. */
2930 else if (s->ctrlval != NANO_NO_KEY)
2931 sprintf(foo, "^%c", s->ctrlval + 64);
2932 else if (s->metaval != NANO_NO_KEY)
2933 sprintf(foo, "M-%c", toupper(s->metaval));
2934
2935 keystr = foo;
2936#ifndef NANO_SMALL
2937 }
2938#endif
2939
2940 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002941 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002942 }
2943
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002944 wnoutrefresh(bottomwin);
2945 reset_cursor();
2946 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002947}
2948
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002949/* Write a shortcut key to the help area at the bottom of the window.
2950 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2951 * to write at most len characters, even if len is very small and
2952 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2953 * the whole string! We do not bother padding the entry with blanks. */
2954void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002955{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002956 size_t keystroke_len = strlenpt(keystroke) + 1;
2957
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002958 assert(keystroke != NULL && desc != NULL);
2959
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002960 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002961 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002962 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002963
2964 if (len > keystroke_len)
2965 len -= keystroke_len;
2966 else
2967 len = 0;
2968
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002969 if (len > 0) {
2970 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002971 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002972 }
2973}
2974
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002975/* And so start the display update routines. */
2976
2977#ifndef NDEBUG
2978int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002979{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002980 int check_line = 0;
2981 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002982
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002983 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
2984 check_line++;
2985 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002986}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002987#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00002988
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002989/* nano scrolls horizontally within a line in chunks. This function
2990 * returns the column number of the first character displayed in the
2991 * window when the cursor is at the given column. Note that
2992 * 0 <= column - get_page_start(column) < COLS. */
2993size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002994{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002995 assert(COLS > 0);
2996 if (column == 0 || column < COLS - 1)
2997 return 0;
2998 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002999 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003000 else if (COLS > 2)
3001 return column - (COLS - 2);
3002 else
3003 return column - (COLS - 1);
3004 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003005}
3006
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003007/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003008 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003009void reset_cursor(void)
3010{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003011 /* If we haven't opened any files yet, put the cursor in the top
3012 * left corner of the edit window and get out. */
3013 if (edittop == NULL || current == NULL) {
3014 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003015 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003016 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003017
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003018 current_y = current->lineno - edittop->lineno;
3019 if (current_y < editwinrows) {
3020 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003021 wmove(edit, current_y, x - get_page_start(x));
3022 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003023}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003024
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003025/* edit_add() takes care of the job of actually painting a line into the
3026 * edit window. fileptr is the line to be painted, at row yval of the
3027 * window. converted is the actual string to be written to the window,
3028 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003029 * characters. start is the column number of the first character of
3030 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003031 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003032void edit_add(const filestruct *fileptr, const char *converted, int
3033 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003034{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003035#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003036 size_t startpos = actual_x(fileptr->data, start);
3037 /* The position in fileptr->data of the leftmost character
3038 * that displays at least partially on the window. */
3039 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3040 /* The position in fileptr->data of the first character that is
3041 * completely off the window to the right.
3042 *
3043 * Note that endpos might be beyond the null terminator of the
3044 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003045#endif
3046
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003047 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003048 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003049
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003050 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003051 * just the text that needs it). */
3052 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003053
Chris Allegretta7dd77682001-12-08 19:52:28 +00003054#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00003055 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003056 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003057
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003058 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3059 int x_start;
3060 /* Starting column for mvwaddnstr. Zero-based. */
3061 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003062 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003063 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003064 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003065 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003066 regmatch_t startmatch; /* match position for start_regexp */
3067 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003068
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003069 if (tmpcolor->bright)
3070 wattron(edit, A_BOLD);
3071 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003072 /* Two notes about regexec(). Return value 0 means there is
3073 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003074 * after the match. */
3075
3076 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003077 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003078 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003079
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003080 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003081 * last match. Even though two matches may overlap, we
3082 * want to ignore them, so that we can highlight
3083 * C-strings correctly. */
3084 while (k < endpos) {
3085 /* Note the fifth parameter to regexec(). It says
3086 * not to match the beginning-of-line character
3087 * unless k is 0. If regexec() returns REG_NOMATCH,
3088 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003089 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003090 &startmatch, k == 0 ? 0 :
3091 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003092 break;
3093 /* Translate the match to the beginning of the line. */
3094 startmatch.rm_so += k;
3095 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003096 if (startmatch.rm_so == startmatch.rm_eo) {
3097 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00003098 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003099 } else if (startmatch.rm_so < endpos &&
3100 startmatch.rm_eo > startpos) {
3101 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003102 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003103 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003104 x_start = strnlenpt(fileptr->data,
3105 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003106
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003107 index = actual_x(converted, x_start);
3108
3109 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003110 strnlenpt(fileptr->data,
3111 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003112
3113 assert(0 <= x_start && 0 <= paintlen);
3114
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003115 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003116 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003117 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003118 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003119 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003120 } else {
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003121 /* This is a multi-line regexp. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003122 * First, we have to see if the beginning of the line is
3123 * colored by a start on an earlier line, and an end on
3124 * this line or later.
3125 *
3126 * We find the first line before fileptr matching the
3127 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003128 * end, then go to step two. Otherwise, find the next
3129 * line after start_line matching the end. If that line
3130 * is not before fileptr, then paint the beginning of
3131 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003132 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003133 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003134 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003135 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003136 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003137
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003138 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003139 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003140 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003141 /* If there is an end on this line, there is no need
3142 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003143 if (regexec(tmpcolor->end, start_line->data, 0,
3144 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003145 goto step_two;
3146 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003147 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003148 /* No start found, so skip to the next step. */
3149 if (start_line == NULL)
3150 goto step_two;
3151 /* Now start_line is the first line before fileptr
3152 * containing a start match. Is there a start on this
3153 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003154 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003155 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003156 start_col += startmatch.rm_so;
3157 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003158 if (regexec(tmpcolor->end, start_line->data +
3159 start_col + startmatch.rm_eo, 0, NULL,
3160 start_col + startmatch.rm_eo == 0 ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003161 REG_NOTBOL) == REG_NOMATCH)
3162 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003163 break;
3164 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003165 if (regexec(&tmpcolor->start, start_line->data +
3166 start_col, 1, &startmatch,
3167 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003168 /* No later start on this line. */
3169 goto step_two;
3170 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003171 /* Indeed, there is a start not followed on this line by
3172 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003173
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003174 /* We have already checked that there is no end before
3175 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003176 * the start at all? We don't paint unterminated
3177 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003178 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003179 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003180 regexec(tmpcolor->end, end_line->data, 1,
3181 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003182 end_line = end_line->next;
3183
3184 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003185 if (end_line == NULL || (end_line == fileptr &&
3186 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003187 goto step_two;
3188
3189 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003190 if (end_line != fileptr)
3191 /* If the start of fileptr is on a different line
3192 * from the end, paintlen is -1, meaning that
3193 * everything on the line gets painted. */
3194 paintlen = -1;
3195 else
3196 /* Otherwise, paintlen is the expanded location of
3197 * the end of the match minus the expanded location
3198 * of the beginning of the page. */
3199 paintlen = actual_x(converted,
3200 strnlenpt(fileptr->data, endmatch.rm_eo) -
3201 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003202
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003203 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003204
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003205 step_two:
3206 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003207 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003208
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003209 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003210 if (regexec(&tmpcolor->start,
3211 fileptr->data + start_col, 1, &startmatch,
3212 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
3213 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003214 /* No more starts on this line. */
3215 break;
3216 /* Translate the match to be relative to the
3217 * beginning of the line. */
3218 startmatch.rm_so += start_col;
3219 startmatch.rm_eo += start_col;
3220
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003221 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003222 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003223 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003224 x_start = strnlenpt(fileptr->data,
3225 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003226
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003227 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003228
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003229 if (regexec(tmpcolor->end,
3230 fileptr->data + startmatch.rm_eo, 1, &endmatch,
3231 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003232 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003233 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003234 endmatch.rm_so += startmatch.rm_eo;
3235 endmatch.rm_eo += startmatch.rm_eo;
3236 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003237 * appear on this page, and is the match more
3238 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003239 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003240 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003241 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003242 strnlenpt(fileptr->data,
3243 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003244
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003245 assert(0 <= x_start && x_start < COLS);
3246
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003247 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003248 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003249 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003250 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003251 /* There is no end on this line. But we haven't
3252 * yet looked for one on later lines. */
3253 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003254
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003255 while (end_line != NULL &&
3256 regexec(tmpcolor->end, end_line->data,
3257 0, NULL, 0) == REG_NOMATCH)
3258 end_line = end_line->next;
3259
3260 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003261 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003262
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003263 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003264 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003265 /* We painted to the end of the line, so
3266 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003267 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003268 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003269 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003270 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003271 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003272 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003273
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003274 wattroff(edit, A_BOLD);
3275 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
3276 } /* for tmpcolor in colorstrings */
3277 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003278#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003279
Chris Allegretta7dd77682001-12-08 19:52:28 +00003280#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003281 if (ISSET(MARK_ISSET)
3282 && (fileptr->lineno <= mark_beginbuf->lineno
3283 || fileptr->lineno <= current->lineno)
3284 && (fileptr->lineno >= mark_beginbuf->lineno
3285 || fileptr->lineno >= current->lineno)) {
3286 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003287
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003288 const filestruct *top;
3289 /* Either current or mark_beginbuf, whichever is first. */
3290 size_t top_x;
3291 /* current_x or mark_beginx, corresponding to top. */
3292 const filestruct *bot;
3293 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003294 int x_start;
3295 /* Starting column for mvwaddnstr. Zero-based. */
3296 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003297 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003298 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003299 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003300 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003301
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003302 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003303
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003304 if (top->lineno < fileptr->lineno || top_x < startpos)
3305 top_x = startpos;
3306 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3307 bot_x = endpos;
3308
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003309 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003310 if (top_x < endpos && bot_x > startpos) {
3311 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003312
3313 /* x_start is the expanded location of the beginning of the
3314 * mark minus the beginning of the page. */
3315 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003316
3317 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003318 /* If the end of the mark is off the page, paintlen is
3319 * -1, meaning that everything on the line gets
3320 * painted. */
3321 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003322 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003323 /* Otherwise, paintlen is the expanded location of the
3324 * end of the mark minus the expanded location of the
3325 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003326 paintlen = strnlenpt(fileptr->data, bot_x) -
3327 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003328
3329 /* If x_start is before the beginning of the page, shift
3330 * paintlen x_start characters to compensate, and put
3331 * x_start at the beginning of the page. */
3332 if (x_start < 0) {
3333 paintlen += x_start;
3334 x_start = 0;
3335 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003336
3337 assert(x_start >= 0 && x_start <= strlen(converted));
3338
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003339 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003340
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003341 if (paintlen > 0)
3342 paintlen = actual_x(converted + index, paintlen);
3343
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003344 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003345 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003346 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003347 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003348 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003349 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003350#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003351}
3352
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003353/* Just update one line in the edit buffer. This is basically a wrapper
3354 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003355 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003356 * If fileptr != current, then index is considered 0. The line will be
3357 * displayed starting with fileptr->data[index]. Likely args are
3358 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003359void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003360{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003361 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003362 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003363 char *converted;
3364 /* fileptr->data converted to have tabs and control characters
3365 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003366 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003367
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003368 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003369
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003370 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003371
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003372 /* We assume the line numbers are valid. Is that really true? */
3373 assert(line < 0 || line == check_linenumbers(fileptr));
3374
3375 if (line < 0 || line >= editwinrows)
3376 return;
3377
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003378 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003379 mvwaddstr(edit, line, 0, hblank);
3380
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003381 /* Next, convert variables that index the line to their equivalent
3382 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003383 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003384 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003385
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003386 /* Expand the line, replacing tabs with spaces, and control
3387 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003388 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003389
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003390 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003391 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003392 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003393
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003394 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003395 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003396 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003397 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003398}
3399
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003400/* Return a nonzero value if we need an update after moving
3401 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003402 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003403int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003404{
3405 return
3406#ifndef NANO_SMALL
3407 ISSET(MARK_ISSET) ||
3408#endif
3409 get_page_start(old_pww) != get_page_start(placewewant);
3410}
3411
3412/* Return a nonzero value if we need an update after moving vertically.
3413 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003414 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003415int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003416{
3417 return
3418#ifndef NANO_SMALL
3419 ISSET(MARK_ISSET) ||
3420#endif
3421 get_page_start(old_pww) != get_page_start(placewewant);
3422}
3423
3424/* Scroll the edit window in the given direction and the given number
3425 * of lines, and draw new lines on the blank lines left after the
3426 * scrolling. direction is the direction to scroll, either UP or DOWN,
3427 * and nlines is the number of lines to scroll. Don't redraw the old
3428 * topmost or bottommost line (where we assume current is) before
3429 * scrolling or draw the new topmost or bottommost line after scrolling
3430 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003431 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003432void edit_scroll(updown direction, int nlines)
3433{
3434 filestruct *foo;
3435 int i, scroll_rows = 0;
3436
3437 /* Scrolling less than one line or more than editwinrows lines is
3438 * redundant, so don't allow it. */
3439 if (nlines < 1 || nlines > editwinrows)
3440 return;
3441
3442 /* Move the top line of the edit window up or down (depending on the
3443 * value of direction) nlines lines. If there are fewer lines of
3444 * text than that left, move it to the top or bottom line of the
3445 * file (depending on the value of direction). Keep track of
3446 * how many lines we moved in scroll_rows. */
3447 for (i = nlines; i > 0; i--) {
3448 if (direction == UP) {
3449 if (edittop->prev == NULL)
3450 break;
3451 edittop = edittop->prev;
3452 scroll_rows--;
3453 } else {
3454 if (edittop->next == NULL)
3455 break;
3456 edittop = edittop->next;
3457 scroll_rows++;
3458 }
3459 }
3460
3461 /* Scroll the text on the screen up or down scroll_rows lines,
3462 * depending on the value of direction. */
3463 scrollok(edit, TRUE);
3464 wscrl(edit, scroll_rows);
3465 scrollok(edit, FALSE);
3466
3467 foo = edittop;
3468 if (direction != UP) {
3469 int slines = editwinrows - nlines;
3470 for (; slines > 0 && foo != NULL; slines--)
3471 foo = foo->next;
3472 }
3473
3474 /* And draw new lines on the blank top or bottom lines of the edit
3475 * window, depending on the value of direction. Don't draw the new
3476 * topmost or new bottommost line. */
3477 while (scroll_rows != 0 && foo != NULL) {
3478 if (foo->next != NULL)
3479 update_line(foo, 0);
3480 if (direction == UP)
3481 scroll_rows++;
3482 else
3483 scroll_rows--;
3484 foo = foo->next;
3485 }
3486}
3487
3488/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003489 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003490void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003491{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003492 int do_refresh = need_vertical_update(0) ||
3493 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003494 const filestruct *foo;
3495
3496 /* If either old_current or current is offscreen, refresh the screen
3497 * and get out. */
3498 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3499 edittop->lineno + editwinrows || current->lineno <
3500 edittop->lineno || current->lineno >= edittop->lineno +
3501 editwinrows) {
3502 edit_refresh();
3503 return;
3504 }
3505
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003506 /* Update old_current and current if we're not on the first page
3507 * and/or we're not on the same page as before. If the mark is on,
3508 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003509 foo = old_current;
3510 while (foo != current) {
3511 if (do_refresh)
3512 update_line(foo, 0);
3513#ifndef NANO_SMALL
3514 if (!ISSET(MARK_ISSET))
3515#endif
3516 break;
3517 if (foo->lineno > current->lineno)
3518 foo = foo->prev;
3519 else
3520 foo = foo->next;
3521 }
3522 if (do_refresh)
3523 update_line(current, current_x);
3524}
3525
Chris Allegretta6df90f52002-07-19 01:08:59 +00003526/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003527void edit_refresh(void)
3528{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003529 if (current->lineno < edittop->lineno ||
3530 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003531 /* Note that edit_update() changes edittop so that it's in range
3532 * of current. Thus, when it then calls edit_refresh(), there
3533 * is no danger of getting an infinite loop. */
3534 edit_update(
3535#ifndef NANO_SMALL
3536 ISSET(SMOOTHSCROLL) ? NONE :
3537#endif
3538 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003539 else {
3540 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003541 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003542
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003543#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003544 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003545#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003546
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003547 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003548 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003549 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003550 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003551 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003552 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003553 }
3554 while (nlines < editwinrows) {
3555 mvwaddstr(edit, nlines, 0, hblank);
3556 nlines++;
3557 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003558 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003559 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003560 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003561}
3562
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003563/* A nice generic routine to update the edit buffer. We keep current in
3564 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003565void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003566{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003567 filestruct *foo = current;
3568
Chris Allegretta6df90f52002-07-19 01:08:59 +00003569 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003570 /* If location is CENTER, we move edittop up (editwinrows / 2)
3571 * lines. This puts current at the center of the screen. If
3572 * location is NONE, we move edittop up current_y lines if
3573 * current_y is in range of the screen, 0 lines if current_y is
3574 * less than 0, or (editwinrows - 1) lines if current_y is
3575 * greater than (editwinrows - 1). This puts current at the
3576 * same place on the screen as before, or at the top or bottom
3577 * of the screen if edittop is beyond either. */
3578 int goal;
3579
3580 if (location == CENTER)
3581 goal = editwinrows / 2;
3582 else {
3583 goal = current_y;
3584
3585 /* Limit goal to (editwinrows - 1) lines maximum. */
3586 if (goal > editwinrows - 1)
3587 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003588 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003589
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003590 for (; goal > 0 && foo->prev != NULL; goal--)
3591 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003592 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003593
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003594 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003595 edit_refresh();
3596}
3597
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003598/* Ask a simple yes/no question, specified in msg, on the statusbar.
3599 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3600 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003601int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003602{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003603 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003604 const char *yesstr; /* String of yes characters accepted. */
3605 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003606 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003607
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003608 /* yesstr, nostr, and allstr are strings of any length. Each string
3609 * consists of all characters accepted as a valid character for that
3610 * value. The first value will be the one displayed in the
3611 * shortcuts. Translators: if possible, specify both the shortcuts
3612 * for your language and English. For example, in French: "OoYy"
3613 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003614 yesstr = _("Yy");
3615 nostr = _("Nn");
3616 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003617
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003618 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003619 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003620
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003621 if (COLS < 32)
3622 width = COLS / 2;
3623
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003624 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003625 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003626
Chris Allegretta6232d662002-05-12 19:52:15 +00003627 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003628 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003629 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003630
3631 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003632 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003633 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003634 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003635 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003636
Chris Allegrettadb28e962003-01-28 01:23:40 +00003637 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003638 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003639 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003640
Chris Allegrettadb28e962003-01-28 01:23:40 +00003641 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003642 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003643 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003644
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003645 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003646
3647 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003648 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003649
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003650 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003651
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003652 wrefresh(bottomwin);
3653
Chris Allegrettadb28e962003-01-28 01:23:40 +00003654 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003655 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003656 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003657#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003658 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003659#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003660
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003661 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003662
3663 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003664 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003665#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003666 /* Look, ma! We get to duplicate lots of code from
3667 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003668 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003669 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003670
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003671 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003672 wenclose(bottomwin, mouse_y, mouse_x) &&
3673 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003674 int x = mouse_x / width;
3675 /* Did we click in the first column of shortcuts, or
3676 * the second? */
3677 int y = mouse_y - editwinrows - 3;
3678 /* Did we click in the first row of shortcuts? */
3679
3680 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3681
3682 /* x = 0 means they clicked Yes or No.
3683 * y = 0 means Yes or All. */
3684 ok = -2 * x * y + x - y + 1;
3685
3686 if (ok == 2 && !all)
3687 ok = -2;
3688 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003689 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003690#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003691 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003692 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003693 else if (strchr(yesstr, kbinput) != NULL)
3694 ok = 1;
3695 else if (strchr(nostr, kbinput) != NULL)
3696 ok = 0;
3697 else if (all && strchr(allstr, kbinput) != NULL)
3698 ok = 2;
3699 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003700
Chris Allegrettadb28e962003-01-28 01:23:40 +00003701 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003702}
3703
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003704void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003705{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003706 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003707 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003708 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003709 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003710 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003711 wnoutrefresh(bottomwin);
3712 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003713 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003714 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003715 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003716 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003717 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003718 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003719}
3720
3721void display_main_list(void)
3722{
3723 bottombars(main_list);
3724}
3725
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003726/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3727 * display the cursor position. Otherwise, we display it only if the
3728 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003729 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003730 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3731 * old_i and old_totsize. That way, we leave the current statusbar
3732 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003733void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003734{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003735 char c;
3736 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003737 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003738 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003739
Chris Allegrettad26ab912003-01-28 01:16:47 +00003740 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003741
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003742 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003743 old_totsize = totsize;
3744
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003745 c = current->data[current_x];
3746 f = current->next;
3747 current->data[current_x] = '\0';
3748 current->next = NULL;
3749 get_totals(fileage, current, NULL, &i);
3750 current->data[current_x] = c;
3751 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003752
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003753 /* Check whether totsize is correct. Else there is a bug
3754 * somewhere. */
3755 assert(current != filebot || i == totsize);
3756
Chris Allegrettad26ab912003-01-28 01:16:47 +00003757 if (constant && ISSET(DISABLE_CURPOS)) {
3758 UNSET(DISABLE_CURPOS);
3759 old_i = i;
3760 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003761 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003762 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003763
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003764 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003765 * unconditionally; otherwise, only display the position when the
3766 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003767 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003768 size_t xpt = xplustabs() + 1;
3769 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003770 int linepct = 100 * current->lineno / totlines;
3771 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003772 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003773
3774 statusbar(
3775 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3776 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003777 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003778 (unsigned long)i, (unsigned long)totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003779 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003780 }
3781
3782 old_i = i;
3783 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003784}
3785
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003786void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003787{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003788 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003789}
3790
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003791#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003792/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003793int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003794{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003795 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003796
3797 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3798 ptr++;
3799 j++;
3800 }
3801 if (j == COLS - 5) {
3802 /* Don't wrap at the first of two spaces following a period. */
3803 if (*ptr == ' ' && *(ptr + 1) == ' ')
3804 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003805 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003806 while (*ptr != ' ' && j > 0) {
3807 ptr--;
3808 j--;
3809 }
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003810 /* A word longer than (COLS - 5) chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003811 if (j == 0)
3812 j = COLS - 5;
3813 }
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003814
Chris Allegretta4640fe32003-02-10 03:10:03 +00003815 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003816
Chris Allegretta4640fe32003-02-10 03:10:03 +00003817 return j;
3818}
3819
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003820/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003821void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003822{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003823 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003824 /* The line number in help_text of the first displayed help
3825 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003826 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003827 /* no_more means the end of the help text is shown, so don't go
3828 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003829 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003830 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003831
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003832 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003833#ifndef DISABLE_MOUSE
3834 const shortcut *oldshortcut = currshortcut;
3835 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003836 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003837#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003838
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003839 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003840 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003841 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003842 blank_statusbar();
3843
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003844 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003845 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003846 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003847
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003848#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003849 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003850 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003851 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003852#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003853
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003854 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003855 /* Make sure that the help screen's shortcut list will actually
3856 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003857 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003858 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003859 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003860
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003861 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003862
3863 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003864 int i;
3865 int old_line = line;
3866 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003867 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003868
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003869 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003870#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003871 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003872 {
3873 int mouse_x, mouse_y;
3874 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3875 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003876 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003877#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003878 case NANO_NEXTPAGE_KEY:
3879 case NANO_NEXTPAGE_FKEY:
3880 if (!no_more)
3881 line += editwinrows - 2;
3882 break;
3883 case NANO_PREVPAGE_KEY:
3884 case NANO_PREVPAGE_FKEY:
3885 if (line > 0) {
3886 line -= editwinrows - 2;
3887 if (line < 0)
3888 line = 0;
3889 }
3890 break;
3891 case NANO_PREVLINE_KEY:
3892 if (line > 0)
3893 line--;
3894 break;
3895 case NANO_NEXTLINE_KEY:
3896 if (!no_more)
3897 line++;
3898 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003899 }
3900
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003901 if (line == old_line && kbinput != ERR)
3902 goto skip_redisplay;
3903
3904 blank_edit();
3905
3906 assert(COLS > 5);
3907
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003908 /* Calculate where in the text we should be, based on the
3909 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003910 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003911 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003912 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003913 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003914 }
3915
Chris Allegretta4640fe32003-02-10 03:10:03 +00003916 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003917 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003918
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003919 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003920 ptr += j;
3921 if (*ptr == '\n')
3922 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003923 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003924 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003925
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003926 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003927 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003928 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3929 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003930
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003931#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003932 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003933#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003934
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003935 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003936 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003937 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003938 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003939 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003940 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003941 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003942
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003943 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003944 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003945
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003946 /* The help_init() at the beginning allocated help_text. Since
3947 * help_text has now been written to the screen, we don't need it
3948 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003949 free(help_text);
3950 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003951}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003952#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003953
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003954/* Highlight the current word being replaced or spell checked. We
3955 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003956void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003957{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003958 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003959 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003960
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003961 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003962 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003963 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003964
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003965 assert(y > 0);
3966
3967 if (word_len > y)
3968 y--;
3969
Chris Allegrettafb62f732000-12-05 11:36:41 +00003970 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003971
Chris Allegrettafb62f732000-12-05 11:36:41 +00003972 if (highlight_flag)
3973 wattron(edit, A_REVERSE);
3974
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003975#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003976 /* This is so we can show zero-length regexes. */
3977 if (word_len == 0)
3978 waddstr(edit, " ");
3979 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003980#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003981 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003982
3983 if (word_len > y)
3984 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003985
3986 if (highlight_flag)
3987 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003988}
3989
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003990#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003991/* Dump the passed-in file structure to stderr. */
3992void dump_buffer(const filestruct *inptr)
3993{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003994 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003995 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003996 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003997 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003998 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003999 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004000
4001 while (inptr != NULL) {
4002 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4003 inptr = inptr->next;
4004 }
4005}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004006
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004007/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004008void dump_buffer_reverse(void)
4009{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004010 const filestruct *fileptr = filebot;
4011
4012 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004013 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004014 fileptr = fileptr->prev;
4015 }
4016}
4017#endif /* DEBUG */
4018
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004019#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004020#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004021#define XLCREDIT_LEN 8
4022
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004023/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004024void do_credits(void)
4025{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004026 int crpos = 0, xlpos = 0;
4027 const char *credits[CREDIT_LEN] = {
4028 NULL, /* "The nano text editor" */
4029 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004030 VERSION,
4031 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004032 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004033 "Chris Allegretta",
4034 "Jordi Mallach",
4035 "Adam Rogoyski",
4036 "Rob Siemborski",
4037 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004038 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004039 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004040 "Ken Tyler",
4041 "Sven Guckes",
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004042#ifdef NANO_WIDE
David Lawrence Ramsey487d08c2005-01-12 18:16:17 +00004043 !ISSET(NO_UTF8) ? "Florian König" :
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004044#endif
4045 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00004046 "Pauli Virtanen",
4047 "Daniele Medri",
4048 "Clement Laforet",
4049 "Tedi Heriyanto",
4050 "Bill Soudan",
4051 "Christian Weisgerber",
4052 "Erik Andersen",
4053 "Big Gaute",
4054 "Joshua Jensen",
4055 "Ryan Krebs",
4056 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004057 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004058 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004059 "Plattsburgh State University",
4060 "Benet Laboratories",
4061 "Amy Allegretta",
4062 "Linda Young",
4063 "Jeremy Robichaud",
4064 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004065 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004066 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004067 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004068 "Thomas Dickey",
4069 "Pavel Curtis",
4070 "Zeyd Ben-Halim",
4071 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004072 NULL, /* "and anyone else we forgot..." */
4073 NULL, /* "Thank you for using nano!" */
4074 "",
4075 "",
4076 "",
4077 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004078 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004079 "",
4080 "",
4081 "",
4082 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004083 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004084 };
4085
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004086 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004087 N_("The nano text editor"),
4088 N_("version"),
4089 N_("Brought to you by:"),
4090 N_("Special thanks to:"),
4091 N_("The Free Software Foundation"),
4092 N_("For ncurses:"),
4093 N_("and anyone else we forgot..."),
4094 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004095 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004096
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004097 curs_set(0);
4098 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004099 scrollok(edit, TRUE);
4100 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004101 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004102 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004103 blank_statusbar();
4104 blank_bottombars();
4105 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004106 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004107 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004108
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004109 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
4110 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004111 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004112 if (crpos < CREDIT_LEN) {
4113 const char *what = credits[crpos];
4114 size_t start_x;
4115
4116 if (what == NULL) {
4117 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00004118 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004119 xlpos++;
4120 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004121 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramseyeb711b02004-12-05 22:24:39 +00004122 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x,
4123 what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004124 }
4125 napms(700);
4126 scroll(edit);
4127 wrefresh(edit);
4128 if (wgetch(edit) != ERR)
4129 break;
4130 napms(700);
4131 scroll(edit);
4132 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004133 }
4134
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004135 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004136 nodelay(edit, FALSE);
4137 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004138 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004139}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004140#endif