blob: 51dd9220640001c634e4ca9d1cc4bc0a78465593 [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 * *
David Lawrence Ramsey6e925cf2005-05-15 19:57:17 +000011 * This program is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * General Public License for more details. *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000015 * *
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 *
David Lawrence Ramsey6e925cf2005-05-15 19:57:17 +000018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
19 * 02110-1301, USA. *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000020 * *
21 **************************************************************************/
22
Jordi Mallach55381aa2004-11-17 23:17:05 +000023#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000026
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000027#include <stdarg.h>
28#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000029#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000030#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000031#include <ctype.h>
Chris Allegretta6232d662002-05-12 19:52:15 +000032#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000033#include "proto.h"
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000034
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 Ramseya17a1302005-03-16 14:39:42 +0000187
188#ifdef DEBUG
189 fprintf(stderr, "get_buffer(): key_buffer_len = %lu\n", (unsigned long)key_buffer_len);
190#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000191}
192
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000193/* Return the length of the default keystroke buffer. */
194size_t get_buffer_len(void)
195{
196 return key_buffer_len;
197}
198
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000199/* Add the contents of the keystroke buffer input to the default
200 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000201void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000202{
203#ifndef NANO_SMALL
204 allow_pending_sigwinch(TRUE);
205 allow_pending_sigwinch(FALSE);
206#endif
207
208 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000209 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000210 return;
211
212 /* If adding input would put the default keystroke buffer beyond
213 * maximum capacity, only add enough of input to put it at maximum
214 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000215 if (key_buffer_len + input_len < key_buffer_len)
216 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000217
218 /* Add the length of input to the length of the default keystroke
219 * buffer, and reallocate the default keystroke buffer so that it
220 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000221 key_buffer_len += input_len;
222 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
223 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000224
225 /* If the default keystroke buffer wasn't empty before, move its
226 * beginning forward far enough so that we can add input to its
227 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000228 if (key_buffer_len > input_len)
229 memmove(key_buffer + input_len, key_buffer,
230 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000231
232 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000233 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000234}
235
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000236/* Put back the character stored in kbinput, putting it in byte range
237 * beforehand. If meta_key is TRUE, put back the Escape character after
238 * putting back kbinput. If func_key is TRUE, put back the function key
239 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000240void unget_kbinput(int kbinput, bool meta_key, bool func_key)
241{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000242 if (!func_key)
243 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000244
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000245 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000246
247 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000248 kbinput = NANO_CONTROL_3;
249 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000250 }
251}
252
253/* Try to read input_len characters from the default keystroke buffer.
254 * If the default keystroke buffer is empty and win isn't NULL, try to
255 * read in more characters from win and add them to the default
256 * keystroke buffer before doing anything else. If the default
257 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000258int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000259{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000260 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000261
262#ifndef NANO_SMALL
263 allow_pending_sigwinch(TRUE);
264 allow_pending_sigwinch(FALSE);
265#endif
266
267 if (key_buffer_len == 0) {
268 if (win != NULL)
269 get_buffer(win);
270
271 if (key_buffer_len == 0)
272 return NULL;
273 }
274
275 /* If input_len is greater than the length of the default keystroke
276 * buffer, only read the number of characters in the default
277 * keystroke buffer. */
278 if (input_len > key_buffer_len)
279 input_len = key_buffer_len;
280
281 /* Subtract input_len from the length of the default keystroke
282 * buffer, and allocate the keystroke buffer input so that it
283 * has enough room for input_len keystrokes. */
284 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000285 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000286
287 /* Copy input_len characters from the beginning of the default
288 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000289 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000290
291 /* If the default keystroke buffer is empty, mark it as such. */
292 if (key_buffer_len == 0) {
293 free(key_buffer);
294 key_buffer = NULL;
295 /* If the default keystroke buffer isn't empty, move its
296 * beginning forward far enough back so that the keystrokes in input
297 * are no longer at its beginning. */
298 } else {
299 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000300 sizeof(int));
301 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
302 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000303 }
304
305 return input;
306}
307
308/* Read in a single character. If it's ignored, swallow it and go on.
309 * Otherwise, try to translate it from ASCII, meta key sequences, escape
310 * sequences, and/or extended keypad values. Set meta_key to TRUE when
311 * we get a meta key sequence, and set func_key to TRUE when we get an
312 * extended keypad value. Supported extended keypad values consist of
313 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
314 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
315 * the function keypad (F1-F16), and the numeric keypad with NumLock
316 * off. Assume nodelay(win) is FALSE. */
317int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
318{
319 int kbinput;
320
321 /* Read in a character and interpret it. Continue doing this until
322 * we get a recognized value or sequence. */
323 while ((kbinput = parse_kbinput(win, meta_key, func_key
324#ifndef NANO_SMALL
325 , FALSE
326#endif
327 )) == ERR);
328
329 return kbinput;
330}
331
332/* Translate ASCII characters, extended keypad values, and escape
333 * sequences into their corresponding key values. Set meta_key to TRUE
334 * when we get a meta key sequence, and set func_key to TRUE when we get
335 * a function key. Assume nodelay(win) is FALSE. */
336int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000337#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000338 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000339#endif
340 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000341
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000342{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000343 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000344 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000345
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000346#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000347 if (reset) {
348 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000349 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000350 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000351 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000352#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000353
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000354 *meta_key = FALSE;
355 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000356
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000357 /* Read in a character. */
358 while ((kbinput = get_input(win, 1)) == NULL);
359
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000360 switch (*kbinput) {
361 case ERR:
362 break;
363 case NANO_CONTROL_3:
364 /* Increment the escape counter. */
365 escapes++;
366 switch (escapes) {
367 case 1:
368 /* One escape: wait for more input. */
369 case 2:
370 /* Two escapes: wait for more input. */
371 break;
372 default:
373 /* More than two escapes: reset the escape counter
374 * and wait for more input. */
375 escapes = 0;
376 }
377 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000378#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000379 /* Since we don't change the default SIGWINCH handler when
380 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
381 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
382 case KEY_RESIZE:
383 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000384#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000385#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000386 case KEY_SHIFT_L:
387 case KEY_SHIFT_R:
388 case KEY_CONTROL_L:
389 case KEY_CONTROL_R:
390 case KEY_ALT_L:
391 case KEY_ALT_R:
392 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000393#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000394 default:
395 switch (escapes) {
396 case 0:
397 switch (*kbinput) {
398 case NANO_CONTROL_8:
399 retval = ISSET(REBIND_DELETE) ?
400 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
401 break;
402 case KEY_DOWN:
403 retval = NANO_NEXTLINE_KEY;
404 break;
405 case KEY_UP:
406 retval = NANO_PREVLINE_KEY;
407 break;
408 case KEY_LEFT:
409 retval = NANO_BACK_KEY;
410 break;
411 case KEY_RIGHT:
412 retval = NANO_FORWARD_KEY;
413 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000414#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000415 /* HP-UX 10 and 11 don't support KEY_HOME. */
416 case KEY_HOME:
417 retval = NANO_HOME_KEY;
418 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000419#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000420 case KEY_BACKSPACE:
421 retval = NANO_BACKSPACE_KEY;
422 break;
423 case KEY_DC:
424 retval = ISSET(REBIND_DELETE) ?
425 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
426 break;
427 case KEY_IC:
428 retval = NANO_INSERTFILE_KEY;
429 break;
430 case KEY_NPAGE:
431 retval = NANO_NEXTPAGE_KEY;
432 break;
433 case KEY_PPAGE:
434 retval = NANO_PREVPAGE_KEY;
435 break;
436 case KEY_ENTER:
437 retval = NANO_ENTER_KEY;
438 break;
439 case KEY_A1: /* Home (7) on numeric keypad
440 * with NumLock off. */
441 retval = NANO_HOME_KEY;
442 break;
443 case KEY_A3: /* PageUp (9) on numeric keypad
444 * with NumLock off. */
445 retval = NANO_PREVPAGE_KEY;
446 break;
447 case KEY_B2: /* Center (5) on numeric keypad
448 * with NumLock off. */
449 break;
450 case KEY_C1: /* End (1) on numeric keypad
451 * with NumLock off. */
452 retval = NANO_END_KEY;
453 break;
454 case KEY_C3: /* PageDown (4) on numeric
455 * keypad with NumLock off. */
456 retval = NANO_NEXTPAGE_KEY;
457 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000458#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000459 /* Slang doesn't support KEY_BEG. */
460 case KEY_BEG: /* Center (5) on numeric keypad
461 * with NumLock off. */
462 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000463#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000464#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000465 /* HP-UX 10 and 11 don't support KEY_END. */
466 case KEY_END:
467 retval = NANO_END_KEY;
468 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000469#endif
470#ifdef KEY_SUSPEND
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000471 /* Slang doesn't support KEY_SUSPEND. */
472 case KEY_SUSPEND:
473 retval = NANO_SUSPEND_KEY;
474 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000475#endif
476#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000477 /* Slang doesn't support KEY_SLEFT. */
478 case KEY_SLEFT:
479 retval = NANO_BACK_KEY;
480 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000481#endif
482#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000483 /* Slang doesn't support KEY_SRIGHT. */
484 case KEY_SRIGHT:
485 retval = NANO_FORWARD_KEY;
486 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000487#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000488 default:
489 retval = *kbinput;
490 break;
491 }
492 break;
493 case 1:
494 /* One escape followed by a non-escape: escape
495 * sequence mode. Reset the escape counter. If
496 * there aren't any other keys waiting, we have a
497 * meta key sequence, so set meta_key to TRUE and
498 * save the lowercase version of the non-escape
499 * character as the result. If there are other keys
500 * waiting, we have a true escape sequence, so
501 * interpret it. */
502 escapes = 0;
503 if (get_buffer_len() == 0) {
504 *meta_key = TRUE;
505 retval = tolower(*kbinput);
506 } else {
507 int *seq;
508 size_t seq_len;
509 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000510
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000511 /* Put back the non-escape character, get the
512 * complete escape sequence, translate the
513 * sequence into its corresponding key value,
514 * and save that as the result. */
515 unget_input(kbinput, 1);
516 seq_len = get_buffer_len();
517 seq = get_input(NULL, seq_len);
518 retval = get_escape_seq_kbinput(seq, seq_len,
519 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000520
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000521 /* If the escape sequence is unrecognized and
522 * not ignored, put back all of its characters
523 * except for the initial escape. */
524 if (retval == ERR && !ignore_seq)
525 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000526
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000527 free(seq);
528 }
529 break;
530 case 2:
531 /* Two escapes followed by one or more decimal
532 * digits: byte sequence mode. If the word
533 * sequence's range is limited to 2XX (the first
534 * digit is in the '0' to '2' range and it's the
535 * first digit, or it's in the '0' to '9' range and
536 * it's not the first digit), increment the byte
537 * sequence counter and interpret the digit. If the
538 * byte sequence's range is not limited to 2XX, fall
539 * through. */
540 if (('0' <= *kbinput && *kbinput <= '6' &&
541 byte_digits == 0) || ('0' <= *kbinput &&
542 *kbinput <= '9' && byte_digits > 0)) {
543 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000544
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000545 byte_digits++;
546 byte = get_byte_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000547#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000548 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000549#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000550 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000551
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000552 if (byte != ERR) {
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000553 char *byte_mb;
554 int byte_mb_len, *seq, i;
555
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000556 /* If we've read in a complete byte
557 * sequence, reset the byte sequence counter
558 * and the escape counter, and put back the
559 * corresponding byte value. */
560 byte_digits = 0;
561 escapes = 0;
562
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000563 /* Put back the multibyte equivalent of the
564 * byte value. */
565 byte_mb = make_mbchar(byte, &byte_mb_len);
566
567 seq = (int *)nmalloc(byte_mb_len *
568 sizeof(int));
569
570 for (i = 0; i < byte_mb_len; i++)
571 seq[i] = (unsigned char)byte_mb[i];
572
573 unget_input(seq, byte_mb_len);
574
575 free(byte_mb);
576 free(seq);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000577 }
578 } else {
579 /* Reset the escape counter. */
580 escapes = 0;
581 if (byte_digits == 0)
582 /* Two escapes followed by a non-decimal
583 * digit or a decimal digit that would
584 * create a byte sequence greater than 2XX,
585 * and we're not in the middle of a byte
586 * sequence: control character sequence
587 * mode. Interpret the control sequence and
588 * save the corresponding control character
589 * as the result. */
590 retval = get_control_kbinput(*kbinput);
591 else {
592 /* If we're in the middle of a byte
593 * sequence, reset the byte sequence counter
594 * and save the character we got as the
595 * result. */
596 byte_digits = 0;
597 retval = *kbinput;
598 }
599 }
600 break;
601 }
602 }
603
604 /* If we have a result and it's an extended keypad value (i.e, a
605 * value outside of byte range), set func_key to TRUE. */
606 if (retval != ERR)
607 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000608
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000609#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000610 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 +0000611#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000612
613 /* Return the result. */
614 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000615}
616
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000617/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000618 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000619 * are generated when the keypad doesn't support the needed keys. If
620 * the escape sequence is recognized but we want to ignore it, return
621 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
622 * set ignore_seq to FALSE. Assume that Escape has already been read
623 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000624int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000625 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000626{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000627 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000628
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000629 *ignore_seq = FALSE;
630
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000631 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000632 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000633 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000634 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000635 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000636 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000637 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000638 case 'P': /* Esc O 2 P == F13 on
639 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000640 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000641 break;
642 case 'Q': /* Esc O 2 Q == F14 on
643 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000644 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000645 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000646 case 'R': /* Esc O 2 R == F15 on
647 * xterm. */
648 retval = KEY_F(15);
649 break;
650 case 'S': /* Esc O 2 S == F16 on
651 * xterm. */
652 retval = KEY_F(16);
653 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000654 }
655 }
656 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000657 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
658 case 'B': /* Esc O B == Down on
659 * VT100/VT320/xterm. */
660 case 'C': /* Esc O C == Right on
661 * VT100/VT320/xterm. */
662 case 'D': /* Esc O D == Left on
663 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000664 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000665 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000666 case 'E': /* Esc O E == Center (5) on numeric keypad
667 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000668 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000669 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000670 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000671 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000672 break;
673 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000674 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000675 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000676 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000677 * NumLock off on VT100/VT220/VT320/xterm/
678 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000679 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000680 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000681 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000682 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000683 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000684 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000685 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000686 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000687 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000688 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000689 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000690 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000691 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000692 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000693 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000694 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000695 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000696 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000697 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000698 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000699 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000700 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000701 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000702 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000703 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000704 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000705 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000706 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000707 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000708 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000709 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000710 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000711 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000712 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000713 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000714 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000715 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000716 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000717 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000718 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000719 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000720 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000721 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000722 * NumLock off on VT100/VT220/VT320/xterm/
723 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000724 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000725 break;
726 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000727 * NumLock off on VT100/VT220/VT320/xterm/
728 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000729 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000730 break;
731 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000732 * NumLock off on VT100/VT220/VT320/xterm/
733 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000734 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000735 break;
736 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000737 * NumLock off on VT100/VT220/VT320/xterm/
738 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000739 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000740 break;
741 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000742 * with NumLock off on VT100/VT220/VT320/
743 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000744 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000745 break;
746 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000747 * NumLock off on VT100/VT220/VT320/xterm/
748 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000749 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000750 break;
751 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000752 * with NumLock off on VT100/VT220/VT320/
753 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000754 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000755 break;
756 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000757 * with NumLock off on VT100/VT220/VT320/
758 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000759 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000760 break;
761 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000762 * with NumLock off on VT100/VT220/VT320/
763 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000764 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000765 break;
766 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000767 * keypad with NumLock off on VT100/VT220/
768 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000769 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000770 break;
771 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000772 * with NumLock off on VT100/VT220/VT320/
773 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000774 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000775 break;
776 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000777 * with NumLock off on VT100/VT220/VT320/
778 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000779 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000780 break;
781 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000782 * with NumLock off on VT100/VT220/VT320/
783 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000784 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000785 break;
786 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000787 * with NumLock off on VT100/VT220/VT320/
788 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000789 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000790 break;
791 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000792 * with NumLock off on VT100/VT220/VT320/
793 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000794 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000795 break;
796 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000797 * with NumLock off on VT100/VT220/VT320/
798 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000799 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000800 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000801 }
802 break;
803 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000804 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000805 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000806 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000807 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000808 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000809 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000810 break;
811 }
812 break;
813 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000814 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000815 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000816 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000817 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000818 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
819 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000820 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000821 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000822 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
823 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000824 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000825 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000826 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
827 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000828 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000829 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000830 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
831 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000832 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000833 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000834 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
835 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000836 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000837 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000838 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000839 * VT220/VT320/Linux console/
840 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000841 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000842 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000843 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000844 * VT220/VT320/Linux console/
845 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000846 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000847 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000848 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000849 * VT220/VT320/Linux console/
850 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000851 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000852 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000853 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000854 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000855 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000856 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000857 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000858 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000859 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
860 * xterm. */
861 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
862 * xterm. */
863 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
864 * xterm. */
865 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
866 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000867 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000868 break;
869 }
870 }
871 break;
872 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000873 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000874 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000875 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
876 * xterm. */
877 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
878 * xterm. */
879 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
880 * xterm. */
881 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
882 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000883 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000884 break;
885 }
886 }
887 break;
888 }
889 }
890 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000891 default: /* Esc [ 1 ~ == Home on
892 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000893 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000894 break;
895 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000896 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000897 break;
898 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000899 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000900 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000901 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000902 * VT220/VT320/Linux console/
903 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000904 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000905 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000906 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000907 * VT220/VT320/Linux console/
908 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000909 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000910 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000911 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000912 * VT220/VT320/Linux console/
913 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000914 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000915 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000916 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000917 * VT220/VT320/Linux console/
918 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000919 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000920 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000921 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000922 * VT220/VT320/Linux console/
923 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000924 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000925 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000926 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000927 * VT220/VT320/Linux console/
928 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000929 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000930 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000931 case '8': /* Esc [ 2 8 ~ == F15 on
932 * VT220/VT320/Linux console/
933 * rxvt/Eterm. */
934 retval = KEY_F(15);
935 break;
936 case '9': /* Esc [ 2 9 ~ == F16 on
937 * VT220/VT320/Linux console/
938 * rxvt/Eterm. */
939 retval = KEY_F(16);
940 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000941 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000942 * VT220/VT320/Linux console/
943 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000944 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000945 break;
946 }
947 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000948 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000949 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
950 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000951 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000952 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000953 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000954 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000955 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000956 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000957 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
958 * Linux console/xterm; Esc [ 5 ^ ==
959 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000960 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000961 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000962 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
963 * Linux console/xterm; Esc [ 6 ^ ==
964 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000965 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000966 break;
967 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000968 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000969 break;
970 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000971 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000972 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000973 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000974 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000975 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000976 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000977 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000978 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000979 case 'A': /* Esc [ A == Up 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 'B': /* Esc [ B == Down 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 'C': /* Esc [ C == Right 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 Ramsey0381c212004-05-01 01:21:38 +0000988 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000989 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000990 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000991 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000992 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000993 case 'E': /* Esc [ E == Center (5) on numeric keypad
994 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000995 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000996 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000997 case 'F': /* Esc [ F == End on FreeBSD
998 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000999 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001000 break;
1001 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001002 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001003 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001004 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001005 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001006 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001007 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001008 break;
1009 case 'I': /* Esc [ I == PageUp on FreeBSD
1010 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001011 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001012 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001013 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001014 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001015 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001016 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001017 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001018 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001019 break;
1020 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001021 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001022 break;
1023 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001024 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001025 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001026 case 'P': /* Esc [ O P == F1 on
1027 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001028 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001029 break;
1030 case 'Q': /* Esc [ O Q == F2 on
1031 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001032 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001033 break;
1034 case 'R': /* Esc [ O R == F3 on
1035 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001036 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001037 break;
1038 case 'S': /* Esc [ O S == F4 on
1039 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001040 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001041 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001042 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001043 } else {
1044 /* Esc [ O == F3 on FreeBSD console. */
1045 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001046 }
1047 break;
1048 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001049 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001050 break;
1051 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001052 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001053 break;
1054 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001055 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001056 break;
1057 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001058 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001059 break;
1060 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001062 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001063 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001064 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001065 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001066 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001067 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001068 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001069 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001070 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001071 break;
1072 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001073 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001074 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001075 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001076 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001077 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001078 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001079 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001080 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001081 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001082 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001083 case 'c': /* Esc [ c == Shift-Right on rxvt/
1084 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001085 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001086 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001087 break;
1088 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001089 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001090 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001091 case 'A': /* Esc [ [ A == F1 on Linux
1092 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001093 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001094 break;
1095 case 'B': /* Esc [ [ B == F2 on Linux
1096 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001097 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001098 break;
1099 case 'C': /* Esc [ [ C == F3 on Linux
1100 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001101 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001102 break;
1103 case 'D': /* Esc [ [ D == F4 on Linux
1104 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001105 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001106 break;
1107 case 'E': /* Esc [ [ E == F5 on Linux
1108 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001109 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001110 break;
1111 }
1112 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001113 break;
1114 }
1115 break;
1116 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001117 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001118
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001119#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001120 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001121#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001122
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001123 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001124}
1125
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001126/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001127 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001128 * to many escape sequences. */
1129int get_escape_seq_abcd(int kbinput)
1130{
1131 switch (tolower(kbinput)) {
1132 case 'a':
1133 return NANO_PREVLINE_KEY;
1134 case 'b':
1135 return NANO_NEXTLINE_KEY;
1136 case 'c':
1137 return NANO_FORWARD_KEY;
1138 case 'd':
1139 return NANO_BACK_KEY;
1140 default:
1141 return ERR;
1142 }
1143}
1144
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001145/* Translate a byte sequence: turn a three-digit decimal number from
1146 * 000 to 255 into its corresponding byte value. */
1147int get_byte_kbinput(int kbinput
1148#ifndef NANO_SMALL
1149 , bool reset
1150#endif
1151 )
1152{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001153 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001154 int retval = ERR;
1155
1156#ifndef NANO_SMALL
1157 if (reset) {
1158 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001159 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001160 return ERR;
1161 }
1162#endif
1163
1164 /* Increment the byte digit counter. */
1165 byte_digits++;
1166
1167 switch (byte_digits) {
1168 case 1:
1169 /* One digit: reset the byte sequence holder and add the
1170 * digit we got to the 100's position of the byte sequence
1171 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001172 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001173 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001174 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001175 else
1176 /* If the character we got isn't a decimal digit, or if
1177 * it is and it would put the byte sequence out of byte
1178 * range, save it as the result. */
1179 retval = kbinput;
1180 break;
1181 case 2:
1182 /* Two digits: add the digit we got to the 10's position of
1183 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001184 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1185 '6' <= kbinput && kbinput <= '9'))
1186 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001187 else
1188 /* If the character we got isn't a decimal digit, or if
1189 * it is and it would put the byte sequence out of byte
1190 * range, save it as the result. */
1191 retval = kbinput;
1192 break;
1193 case 3:
1194 /* Three digits: add the digit we got to the 1's position of
1195 * the byte sequence holder, and save the corresponding word
1196 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001197 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1198 '6' <= kbinput && kbinput <= '9')) {
1199 byte += (kbinput - '0');
1200 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001201 } else
1202 /* If the character we got isn't a decimal digit, or if
1203 * it is and it would put the word sequence out of word
1204 * range, save it as the result. */
1205 retval = kbinput;
1206 break;
1207 default:
1208 /* More than three digits: save the character we got as the
1209 * result. */
1210 retval = kbinput;
1211 break;
1212 }
1213
1214 /* If we have a result, reset the byte digit counter and the byte
1215 * sequence holder. */
1216 if (retval != ERR) {
1217 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001218 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001219 }
1220
1221#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001222 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 +00001223#endif
1224
1225 return retval;
1226}
1227
1228/* Translate a word sequence: turn a four-digit hexadecimal number from
1229 * 0000 to ffff (case-insensitive) into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001230int get_word_kbinput(int kbinput
1231#ifndef NANO_SMALL
1232 , bool reset
1233#endif
1234 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001235{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001236 static int word_digits = 0, word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001237 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001238
1239#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001240 if (reset) {
1241 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001242 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001243 return ERR;
1244 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001245#endif
1246
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001247 /* Increment the word digit counter. */
1248 word_digits++;
1249
1250 switch (word_digits) {
1251 case 1:
1252 /* One digit: reset the word sequence holder and add the
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001253 * digit we got to the 4096's position of the word sequence
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001254 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001255 word = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001256 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001257 word += (kbinput - '0') * 4096;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001258 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001259 word += (tolower(kbinput) + 10 - 'a') * 4096;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001260 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001261 /* If the character we got isn't a hexadecimal digit, or
1262 * if it is and it would put the word sequence out of
1263 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001264 retval = kbinput;
1265 break;
1266 case 2:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001267 /* Two digits: add the digit we got to the 256's position of
1268 * the word sequence holder. */
1269 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001270 word += (kbinput - '0') * 256;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001271 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001272 word += (tolower(kbinput) + 10 - 'a') * 256;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001273 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001274 /* If the character we got isn't a hexadecimal digit, or
1275 * if it is and it would put the word sequence out of
1276 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001277 retval = kbinput;
1278 break;
1279 case 3:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001280 /* Three digits: add the digit we got to the 16's position
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001281 * of the word sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001282 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001283 word += (kbinput - '0') * 16;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001284 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001285 word += (tolower(kbinput) + 10 - 'a') * 16;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001286 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001287 /* If the character we got isn't a hexadecimal digit, or
1288 * if it is and it would put the word sequence out of
1289 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001290 retval = kbinput;
1291 break;
1292 case 4:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001293 /* Four digits: add the digit we got to the 1's position of
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001294 * the word sequence holder, and save the corresponding word
1295 * value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001296 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001297 word += (kbinput - '0');
1298 retval = word;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001299 } else if ('a' <= tolower(kbinput) &&
1300 tolower(kbinput) <= 'f') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001301 word += (tolower(kbinput) + 10 - 'a');
1302 retval = word;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001303 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001304 /* If the character we got isn't a hexadecimal digit, or
1305 * if it is and it would put the word sequence out of
1306 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001307 retval = kbinput;
1308 break;
1309 default:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001310 /* More than four digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001311 * result. */
1312 retval = kbinput;
1313 break;
1314 }
1315
1316 /* If we have a result, reset the word digit counter and the word
1317 * sequence holder. */
1318 if (retval != ERR) {
1319 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001320 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001321 }
1322
1323#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001324 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 +00001325#endif
1326
1327 return retval;
1328}
1329
1330/* Translate a control character sequence: turn an ASCII non-control
1331 * character into its corresponding control character. */
1332int get_control_kbinput(int kbinput)
1333{
1334 int retval;
1335
1336 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1337 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1338 kbinput == '`')
1339 retval = NANO_CONTROL_SPACE;
1340 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1341 else if ('3' <= kbinput && kbinput <= '7')
1342 retval = kbinput - 24;
1343 /* Ctrl-8 (Ctrl-?) */
1344 else if (kbinput == '8' || kbinput == '?')
1345 retval = NANO_CONTROL_8;
1346 /* Ctrl-A to Ctrl-_ */
1347 else if ('A' <= kbinput && kbinput <= '_')
1348 retval = kbinput - 64;
1349 /* Ctrl-a to Ctrl-~ */
1350 else if ('a' <= kbinput && kbinput <= '~')
1351 retval = kbinput - 96;
1352 else
1353 retval = kbinput;
1354
1355#ifdef DEBUG
1356 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1357#endif
1358
1359 return retval;
1360}
1361
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001362/* Put the output-formatted characters in output back into the default
1363 * keystroke buffer, so that they can be parsed and displayed as output
1364 * again. */
1365void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001366{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001367 int *input;
1368 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001369
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001370 if (output_len == 0)
1371 return;
1372
1373 input = (int *)nmalloc(output_len * sizeof(int));
1374 for (i = 0; i < output_len; i++)
1375 input[i] = (int)output[i];
1376 unget_input(input, output_len);
1377 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001378}
1379
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001380/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001381 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1382int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1383{
1384 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001385
1386 /* Turn off flow control characters if necessary so that we can type
1387 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001388 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001389 if (ISSET(PRESERVE))
1390 disable_flow_control();
1391 keypad(win, FALSE);
1392
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001393 /* Read in a stream of characters and interpret it if possible. */
1394 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001395
1396 /* Turn flow control characters back on if necessary and turn the
1397 * keypad back on now that we're done. */
1398 if (ISSET(PRESERVE))
1399 enable_flow_control();
1400 keypad(win, TRUE);
1401
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001402 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001403}
1404
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001405/* Read in a stream of all available characters, and return the length
1406 * of the string in kbinput_len. Translate the first few characters of
1407 * the input into the corresponding word value if possible. After that,
1408 * leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001409int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001410{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001411 int *kbinput, word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001412
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001413 /* Read in the first keystroke. */
1414 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001415
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001416 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001417 word = get_word_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001418#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001419 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001420#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001421 );
1422
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001423 /* If the first keystroke isn't a hexadecimal digit, put back the
1424 * first keystroke. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001425 if (word != ERR)
1426 unget_input(kbinput, 1);
1427 /* Otherwise, read in keystrokes until we have a complete word
1428 * sequence, and put back the corresponding word value. */
1429 else {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00001430 char *word_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001431 int word_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001432
1433 while (word == ERR) {
1434 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001435
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001436 word = get_word_kbinput(*kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001437#ifndef NANO_SMALL
1438 , FALSE
1439#endif
1440 );
1441 }
1442
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001443 /* Put back the multibyte equivalent of the word value. */
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00001444 word_mb = make_mbchar(word, &word_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001445
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001446 seq = (int *)nmalloc(word_mb_len * sizeof(int));
1447
1448 for (i = 0; i < word_mb_len; i++)
1449 seq[i] = (unsigned char)word_mb[i];
1450
1451 unget_input(seq, word_mb_len);
1452
1453 free(seq);
1454 free(word_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001455 }
1456
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001457 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001458 * result. */
1459 *kbinput_len = get_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001460 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001461
1462 return retval;
1463}
1464
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001465#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001466/* Check for a mouse event, and if one's taken place, save the
1467 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001468 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1469 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001470 * place on it, figure out which shortcut was clicked and put back the
1471 * equivalent keystroke(s). Return FALSE if no keystrokes were
1472 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001473 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001474bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001475{
1476 MEVENT mevent;
1477
1478 *mouse_x = -1;
1479 *mouse_y = -1;
1480
1481 /* First, get the actual mouse event. */
1482 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001483 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001484
1485 /* Save the screen coordinates where the mouse event took place. */
1486 *mouse_x = mevent.x;
1487 *mouse_y = mevent.y;
1488
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001489 /* If we're allowing shortcuts, the current shortcut list is being
1490 * displayed on the last two lines of the screen, and the mouse
1491 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001492 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001493 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1494 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001495 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001496 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001497 /* The number of shortcuts in the current shortcut list. */
1498 const shortcut *s = currshortcut;
1499 /* The actual shortcut we clicked on, starting at the first
1500 * one in the current shortcut list. */
1501
1502 /* Get the shortcut lists' length. */
1503 if (currshortcut == main_list)
1504 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001505 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001506 currslen = length_of_list(currshortcut);
1507
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001508 /* We don't show any more shortcuts than the main list
1509 * does. */
1510 if (currslen > MAIN_VISIBLE)
1511 currslen = MAIN_VISIBLE;
1512 }
1513
David Lawrence Ramsey0df61f12005-06-08 20:23:06 +00001514 /* Calculate the width of each shortcut in the list. It's the
1515 * same for all of them. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001516 if (currslen < 2)
1517 i = COLS / 6;
1518 else
1519 i = COLS / ((currslen / 2) + (currslen % 2));
1520
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001521 /* Calculate the y-coordinate relative to the beginning of
1522 * bottomwin. */
1523 j = *mouse_y - ((2 - no_more_space()) + 1) - editwinrows;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001524
1525 /* If we're on the statusbar, beyond the end of the shortcut
1526 * list, or beyond the end of a shortcut on the right side of
1527 * the screen, don't do anything. */
1528 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001529 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001530 j = (*mouse_x / i) * 2 + j;
1531 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001532 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001533
1534 /* Go through the shortcut list to determine which shortcut was
1535 * clicked. */
1536 for (; j > 0; j--)
1537 s = s->next;
1538
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001539 /* And put back the equivalent key. Assume that each shortcut
1540 * has, at the very least, an equivalent control key, an
1541 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001542 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001543 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001544 return TRUE;
1545 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001546 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001547 return TRUE;
1548 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001549 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001550 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001551}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001552#endif /* !DISABLE_MOUSE */
1553
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001554const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001555 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001556{
1557 const shortcut *s = s_list;
1558 size_t slen = length_of_list(s_list);
1559
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001560#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001561 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 +00001562#endif
1563
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001564 /* Check for shortcuts. */
1565 for (; slen > 0; slen--) {
1566 /* We've found a shortcut if:
1567 *
1568 * 1. The key exists.
1569 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001570 * 3. meta_key is TRUE and the key is the primary or
1571 * miscellaneous meta sequence in the shortcut list.
1572 * 4. func_key is TRUE and the key is a function key in the
1573 * shortcut list. */
1574
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001575 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1576 (*meta_key == TRUE && (*kbinput == s->metaval ||
1577 *kbinput == s->miscval)) || (*func_key == TRUE &&
1578 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001579 break;
1580 }
1581
1582 s = s->next;
1583 }
1584
1585 /* Translate the shortcut to either its control key or its meta key
1586 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001587 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001588 if (slen > 0) {
1589 if (s->ctrlval != NANO_NO_KEY) {
1590 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001591 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001592 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001593 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001594 } else if (s->metaval != NANO_NO_KEY) {
1595 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001596 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001597 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001598 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001599 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001600 }
1601
1602 return NULL;
1603}
1604
1605#ifndef NANO_SMALL
1606const toggle *get_toggle(int kbinput, bool meta_key)
1607{
1608 const toggle *t = toggles;
1609
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001610#ifdef DEBUG
1611 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1612#endif
1613
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001614 /* Check for toggles. */
1615 for (; t != NULL; t = t->next) {
1616 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001617 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001618 if (meta_key && kbinput == t->val)
1619 break;
1620 }
1621
1622 return t;
1623}
1624#endif /* !NANO_SMALL */
1625
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001626int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001627 bool *ran_func, bool *finished, bool allow_funcs)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001628{
1629 int input;
1630 /* The character we read in. */
1631 static int *kbinput = NULL;
1632 /* The input buffer. */
1633 static size_t kbinput_len = 0;
1634 /* The length of the input buffer. */
1635 const shortcut *s;
1636 bool have_shortcut;
1637
1638 *s_or_t = FALSE;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001639 *ran_func = FALSE;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001640 *finished = FALSE;
1641
1642 /* Read in a character. */
1643 input = get_kbinput(bottomwin, meta_key, func_key);
1644
1645#ifndef DISABLE_MOUSE
1646 /* If we got a mouse click and it was on a shortcut, read in the
1647 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001648 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001649 if (do_mouse())
1650 input = get_kbinput(bottomwin, meta_key, func_key);
1651 else
1652 input = ERR;
1653 }
1654#endif
1655
1656 /* Check for a shortcut in the current list. */
1657 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1658
1659 /* If we got a shortcut from the current list, or a "universal"
1660 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1661 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1662 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1663 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1664 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001665 input == NANO_CUT_KEY ||
1666#ifndef NANO_SMALL
1667 input == NANO_NEXTWORD_KEY ||
1668#endif
1669 (*meta_key == TRUE && (
1670#ifndef NANO_SMALL
1671 input == NANO_PREVWORD_KEY ||
1672#endif
1673 input == NANO_VERBATIM_KEY)));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001674
1675 /* Set s_or_t to TRUE if we got a shortcut. */
1676 *s_or_t = have_shortcut;
1677
1678 if (allow_funcs) {
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001679 /* If we got a character, and it isn't a shortcut or toggle,
1680 * it's a normal text character. Display the warning if we're
1681 * in view mode, or add the character to the input buffer if
1682 * we're not. */
1683 if (input != ERR && *s_or_t == FALSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001684 /* If we're using restricted mode, the filename isn't blank,
1685 * and we're at the "Write File" prompt, disable text
1686 * input. */
1687 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1688 currshortcut != writefile_list) {
1689 kbinput_len++;
1690 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1691 sizeof(int));
1692 kbinput[kbinput_len - 1] = input;
1693 }
1694 }
1695
1696 /* If we got a shortcut, or if there aren't any other characters
1697 * waiting after the one we read in, we need to display all the
1698 * characters in the input buffer if it isn't empty. */
1699 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1700 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001701
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001702 /* Display all the characters in the input buffer at
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001703 * once, filtering out control characters. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001704 char *output = charalloc(kbinput_len + 1);
1705 size_t i;
1706 bool got_enter;
1707 /* Whether we got the Enter key. */
1708
1709 for (i = 0; i < kbinput_len; i++)
1710 output[i] = (char)kbinput[i];
1711 output[i] = '\0';
1712
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001713 do_statusbar_output(output, kbinput_len, &got_enter,
1714 FALSE);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001715
1716 free(output);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001717
1718 /* Empty the input buffer. */
1719 kbinput_len = 0;
1720 free(kbinput);
1721 kbinput = NULL;
1722 }
1723 }
1724
1725 if (have_shortcut) {
1726 switch (input) {
1727 /* Handle the "universal" statusbar prompt shortcuts. */
1728 case NANO_REFRESH_KEY:
1729 total_refresh();
1730 break;
1731 case NANO_HOME_KEY:
1732 do_statusbar_home();
1733 break;
1734 case NANO_END_KEY:
1735 do_statusbar_end();
1736 break;
1737 case NANO_FORWARD_KEY:
1738 do_statusbar_right();
1739 break;
1740 case NANO_BACK_KEY:
1741 do_statusbar_left();
1742 break;
1743 case NANO_BACKSPACE_KEY:
1744 /* If we're using restricted mode, the filename
1745 * isn't blank, and we're at the "Write File"
1746 * prompt, disable Backspace. */
1747 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1748 currshortcut != writefile_list)
1749 do_statusbar_backspace();
1750 break;
1751 case NANO_DELETE_KEY:
1752 /* If we're using restricted mode, the filename
1753 * isn't blank, and we're at the "Write File"
1754 * prompt, disable Delete. */
1755 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1756 currshortcut != writefile_list)
1757 do_statusbar_delete();
1758 break;
1759 case NANO_CUT_KEY:
1760 /* If we're using restricted mode, the filename
1761 * isn't blank, and we're at the "Write File"
1762 * prompt, disable Cut. */
1763 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1764 currshortcut != writefile_list)
1765 do_statusbar_cut_text();
1766 break;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001767#ifndef NANO_SMALL
1768 case NANO_NEXTWORD_KEY:
1769 do_statusbar_next_word();
1770 break;
1771 case NANO_PREVWORD_KEY:
1772 if (*meta_key == TRUE)
1773 do_statusbar_prev_word();
1774 break;
1775#endif
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001776 case NANO_VERBATIM_KEY:
1777 if (*meta_key == TRUE) {
1778 /* If we're using restricted mode, the filename
1779 * isn't blank, and we're at the "Write File"
1780 * prompt, disable verbatim input. */
1781 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001782 currshortcut != writefile_list) {
1783 bool got_enter;
1784 /* Whether we got the Enter key. */
1785
1786 do_statusbar_verbatim_input(&got_enter);
1787
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001788 /* If we got the Enter key, set input to the
1789 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001790 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001791 if (got_enter) {
1792 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001793 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001794 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001795 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001796 break;
1797 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001798 /* Handle the normal statusbar prompt shortcuts, setting
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001799 * ran_func to TRUE if we try to run their associated
1800 * functions and setting finished to TRUE to indicate
1801 * that we're done after trying to run their associated
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001802 * functions. */
1803 default:
1804 if (s->func != NULL) {
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001805 *ran_func = TRUE;
1806 if (!ISSET(VIEW_MODE) || s->viewok)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001807 s->func();
1808 }
1809 *finished = TRUE;
1810 }
1811 }
1812 }
1813
1814 return input;
1815}
1816
1817#ifndef DISABLE_MOUSE
1818bool do_statusbar_mouse(void)
1819{
1820 /* FIXME: If we clicked on a location in the statusbar, the cursor
1821 * should move to the location we clicked on. This functionality
1822 * should be in this function. */
1823 int mouse_x, mouse_y;
1824 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1825}
1826#endif
1827
1828void do_statusbar_home(void)
1829{
1830#ifndef NANO_SMALL
1831 if (ISSET(SMART_HOME)) {
1832 size_t statusbar_x_save = statusbar_x;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001833
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001834 statusbar_x = indent_length(answer);
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001835
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001836 if (statusbar_x == statusbar_x_save ||
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001837 statusbar_x == strlen(answer))
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001838 statusbar_x = 0;
1839 } else
1840#endif
1841 statusbar_x = 0;
1842}
1843
1844void do_statusbar_end(void)
1845{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001846 statusbar_x = strlen(answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001847}
1848
1849void do_statusbar_right(void)
1850{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001851 if (statusbar_x < strlen(answer))
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001852 statusbar_x = move_mbright(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001853}
1854
1855void do_statusbar_left(void)
1856{
1857 if (statusbar_x > 0)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001858 statusbar_x = move_mbleft(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001859}
1860
1861void do_statusbar_backspace(void)
1862{
1863 if (statusbar_x > 0) {
1864 do_statusbar_left();
1865 do_statusbar_delete();
1866 }
1867}
1868
1869void do_statusbar_delete(void)
1870{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001871 if (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001872 int char_buf_len = parse_mbchar(answer + statusbar_x, NULL,
1873 NULL, NULL);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001874 size_t line_len = strlen(answer + statusbar_x);
1875
1876 assert(statusbar_x < strlen(answer));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001877
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001878 charmove(answer + statusbar_x, answer + statusbar_x +
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001879 char_buf_len, strlen(answer) - statusbar_x -
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001880 char_buf_len + 1);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001881
1882 null_at(&answer, statusbar_x + line_len - char_buf_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001883 }
1884}
1885
1886void do_statusbar_cut_text(void)
1887{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001888 assert(answer != NULL);
1889
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001890#ifndef NANO_SMALL
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001891 if (ISSET(CUT_TO_END))
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001892 null_at(&answer, statusbar_x);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001893 else {
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001894#endif
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001895 null_at(&answer, 0);
1896 statusbar_x = 0;
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001897#ifndef NANO_SMALL
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001898 }
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001899#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001900}
1901
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001902#ifndef NANO_SMALL
1903void do_statusbar_next_word(void)
1904{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001905 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001906 int char_mb_len;
1907
1908 assert(answer != NULL);
1909
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001910 char_mb = charalloc(mb_cur_max());
1911
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001912 /* Move forward until we find the character after the last letter of
1913 * the current word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001914 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001915 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1916 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001917
1918 /* If we've found it, stop moving forward through the current
1919 * line. */
David Lawrence Ramseye2213112005-06-15 03:03:45 +00001920 if (!is_word_mbchar(char_mb, TRUE))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001921 break;
1922
1923 statusbar_x += char_mb_len;
1924 }
1925
1926 /* Move forward until we find the first letter of the next word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001927 if (answer[statusbar_x] != '\0')
1928 statusbar_x += char_mb_len;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001929
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001930 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001931 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1932 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001933
1934 /* If we've found it, stop moving forward through the current
1935 * line. */
David Lawrence Ramseye2213112005-06-15 03:03:45 +00001936 if (is_word_mbchar(char_mb, TRUE))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001937 break;
1938
1939 statusbar_x += char_mb_len;
1940 }
1941
1942 free(char_mb);
1943}
1944
1945void do_statusbar_prev_word(void)
1946{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001947 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001948 int char_mb_len;
1949 bool begin_line = FALSE;
1950
1951 assert(answer != NULL);
1952
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001953 char_mb = charalloc(mb_cur_max());
1954
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001955 /* Move backward until we find the character before the first letter
1956 * of the current word. */
1957 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001958 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1959 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001960
1961 /* If we've found it, stop moving backward through the current
1962 * line. */
David Lawrence Ramseye2213112005-06-15 03:03:45 +00001963 if (!is_word_mbchar(char_mb, TRUE))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001964 break;
1965
1966 if (statusbar_x == 0)
1967 begin_line = TRUE;
1968 else
1969 statusbar_x = move_mbleft(answer, statusbar_x);
1970 }
1971
1972 /* Move backward until we find the last letter of the previous
1973 * word. */
1974 if (statusbar_x == 0)
1975 begin_line = TRUE;
1976 else
1977 statusbar_x = move_mbleft(answer, statusbar_x);
1978
1979 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001980 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1981 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001982
1983 /* If we've found it, stop moving backward through the current
1984 * line. */
David Lawrence Ramseye2213112005-06-15 03:03:45 +00001985 if (is_word_mbchar(char_mb, TRUE))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001986 break;
1987
1988 if (statusbar_x == 0)
1989 begin_line = TRUE;
1990 else
1991 statusbar_x = move_mbleft(answer, statusbar_x);
1992 }
1993
1994 /* If we've found it, move backward until we find the character
1995 * before the first letter of the previous word. */
1996 if (!begin_line) {
1997 if (statusbar_x == 0)
1998 begin_line = TRUE;
1999 else
2000 statusbar_x = move_mbleft(answer, statusbar_x);
2001
2002 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002003 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
2004 NULL, NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002005
2006 /* If we've found it, stop moving backward through the
2007 * current line. */
David Lawrence Ramseye2213112005-06-15 03:03:45 +00002008 if (!is_word_mbchar(char_mb, TRUE))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002009 break;
2010
2011 if (statusbar_x == 0)
2012 begin_line = TRUE;
2013 else
2014 statusbar_x = move_mbleft(answer, statusbar_x);
2015 }
2016
2017 /* If we've found it, move forward to the first letter of the
2018 * previous word. */
2019 if (!begin_line)
2020 statusbar_x += char_mb_len;
2021 }
2022
2023 free(char_mb);
2024}
2025#endif
2026
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002027void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002028{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002029 int *kbinput;
2030 size_t kbinput_len, i;
2031 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002032
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002033 *got_enter = FALSE;
2034
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002035 /* Read in all the verbatim characters. */
2036 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
2037
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002038 /* Display all the verbatim characters at once, not filtering out
2039 * control characters. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002040 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002041
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002042 for (i = 0; i < kbinput_len; i++)
2043 output[i] = (char)kbinput[i];
2044 output[i] = '\0';
2045
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002046 do_statusbar_output(output, kbinput_len, got_enter, TRUE);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002047
2048 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002049}
2050
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002051void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002052 *got_enter, bool allow_cntrls)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002053{
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002054 size_t answer_len, i = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002055 char *char_buf = charalloc(mb_cur_max());
2056 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002057
2058 assert(answer != NULL);
2059
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002060 answer_len = strlen(answer);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002061 *got_enter = FALSE;
2062
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002063 while (i < output_len) {
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002064 /* If allow_cntrls is FALSE, filter out nulls and newlines,
2065 * since they're control characters. */
2066 if (allow_cntrls) {
2067 /* Null to newline, if needed. */
2068 if (output[i] == '\0')
2069 output[i] = '\n';
2070 /* Newline to Enter, if needed. */
2071 else if (output[i] == '\n') {
2072 /* Set got_enter to TRUE to indicate that we got the
2073 * Enter key, put back the rest of the characters in
2074 * output so that they can be parsed and output again,
2075 * and get out. */
2076 *got_enter = TRUE;
2077 unparse_kbinput(output + i, output_len - i);
2078 return;
2079 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002080 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002081
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002082 /* Interpret the next multibyte character. If it's an invalid
2083 * multibyte character, interpret it as though it's a byte
2084 * character. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002085 char_buf_len = parse_mbchar(output + i, char_buf, NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002086
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002087 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002088
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002089 /* If allow_cntrls is FALSE, filter out a control character. */
2090 if (!allow_cntrls && is_cntrl_mbchar(output + i - char_buf_len))
2091 continue;
2092
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002093 /* More dangerousness fun =) */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002094 answer = charealloc(answer, answer_len + (char_buf_len * 2));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002095
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002096 assert(statusbar_x <= answer_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002097
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002098 charmove(&answer[statusbar_x + char_buf_len],
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002099 &answer[statusbar_x], answer_len - statusbar_x +
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002100 char_buf_len);
2101 charcpy(&answer[statusbar_x], char_buf, char_buf_len);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002102 answer_len += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002103
2104 do_statusbar_right();
2105 }
2106
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002107 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002108}
2109
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002110/* Return the placewewant associated with current_x, i.e, the zero-based
2111 * column position of the cursor. The value will be no smaller than
2112 * current_x. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002113size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002114{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002115 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002116}
2117
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002118/* actual_x() gives the index in str of the character displayed at
2119 * column xplus. That is, actual_x() is the largest value such that
2120 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2121size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002122{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002123 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002124 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002125 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002126 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002127
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002128 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002129
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002130 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002131 int str_len = parse_mbchar(str, NULL, NULL, &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002132
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002133 if (length > xplus)
2134 break;
2135
2136 i += str_len;
2137 str += str_len;
2138 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002139
Chris Allegretta6df90f52002-07-19 01:08:59 +00002140 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002141}
2142
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002143/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002144 * columns wide are the first size characters of str? */
2145size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002146{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002147 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002148 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002149
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002150 if (size == 0)
2151 return 0;
2152
2153 assert(str != NULL);
2154
2155 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002156 int str_len = parse_mbchar(str, NULL, NULL, &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002157
2158 str += str_len;
2159
2160 if (size <= str_len)
2161 break;
2162
2163 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002164 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002165
Chris Allegretta6df90f52002-07-19 01:08:59 +00002166 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002167}
2168
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002169/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002170size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002171{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002172 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002173}
2174
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002175void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002176{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002177 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002178}
2179
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002180void blank_topbar(void)
2181{
2182 if (!ISSET(MORE_SPACE))
2183 mvwaddstr(topwin, 1, 0, hblank);
2184}
2185
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002186void blank_edit(void)
2187{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002188 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002189 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002190 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002191}
2192
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002193void blank_statusbar(void)
2194{
2195 mvwaddstr(bottomwin, 0, 0, hblank);
2196}
2197
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002198void blank_bottombars(void)
2199{
2200 if (!ISSET(NO_HELP)) {
2201 mvwaddstr(bottomwin, 1, 0, hblank);
2202 mvwaddstr(bottomwin, 2, 0, hblank);
2203 }
2204}
2205
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002206void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002207{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002208 if (statusblank > 1)
2209 statusblank--;
2210 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
2211 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002212 blank_statusbar();
2213 wnoutrefresh(bottomwin);
2214 reset_cursor();
2215 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002216 }
2217}
2218
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002219/* Convert buf into a string that can be displayed on screen. The
2220 * caller wants to display buf starting with column start_col, and
2221 * extending for at most len columns. start_col is zero-based. len is
2222 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002223 * string is dynamically allocated, and should be freed. If dollars is
2224 * TRUE, the caller might put "$" at the beginning or end of the line if
2225 * it's too long. */
2226char *display_string(const char *buf, size_t start_col, size_t len, bool
2227 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002228{
2229 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002230 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002231 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002232 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002233 size_t alloc_len;
2234 /* The length of memory allocated for converted. */
2235 char *converted;
2236 /* The string we return. */
2237 size_t index;
2238 /* Current position in converted. */
2239
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002240 char *buf_mb = charalloc(mb_cur_max());
2241 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002242 bool bad_char;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002243
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002244 /* If dollars is TRUE, make room for the "$" at the end of the
2245 * line. */
2246 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2247 len--;
2248
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002249 if (len == 0)
2250 return mallocstrcpy(NULL, "");
2251
2252 start_index = actual_x(buf, start_col);
2253 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002254
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002255 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002256
David Lawrence Ramseyd29b9d52005-06-06 03:17:07 +00002257 /* Allocate enough space for the entire line, accounting for a
2258 * trailing multibyte character and/or tab. */
2259 alloc_len = (mb_cur_max() * (len + 1)) + tabsize;
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002260
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002261 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002262 index = 0;
2263
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002264 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002265 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002266 /* We don't display all of buf[start_index] since it starts to
2267 * the left of the screen. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002268 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL,
2269 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002270
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002271 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002272 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002273 char *ctrl_buf_mb = charalloc(mb_cur_max());
2274 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002275
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002276 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2277 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002278
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002279 for (i = 0; i < ctrl_buf_mb_len; i++)
2280 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002281
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002282 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002283
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002284 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002285
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002286 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002287 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002288 }
2289#ifdef NANO_WIDE
David Lawrence Ramsey7a4aaa52005-06-16 02:09:57 +00002290 else if (ISSET(USE_UTF8) && mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002291 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002292 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002293
2294 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002295 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002296#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002297 }
2298
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002299 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseybc149412005-02-11 20:23:00 +00002300 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, &bad_char,
2301 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002302
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002303 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002304#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002305 if (ISSET(WHITESPACE_DISPLAY)) {
2306 int i;
2307
2308 for (i = 0; i < whitespace_len[0]; i++)
2309 converted[index++] = whitespace[i];
2310 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002311#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002312 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002313 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002314 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002315 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002316 start_col++;
2317 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002318 /* If buf contains a control character, interpret it. If it
2319 * contains an invalid multibyte control character, interpret
2320 * that character as though it's a normal control character. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002321 } else if (is_cntrl_mbchar(buf_mb)) {
2322 char *ctrl_buf_mb = charalloc(mb_cur_max());
2323 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002324
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002325 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002326 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002327
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002328 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2329 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002330
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002331 for (i = 0; i < ctrl_buf_mb_len; i++)
2332 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002333
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002334 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002335
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002336 free(ctrl_buf_mb);
2337 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002338#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002339 if (ISSET(WHITESPACE_DISPLAY)) {
2340 int i;
2341
2342 for (i = whitespace_len[0]; i < whitespace_len[0] +
2343 whitespace_len[1]; i++)
2344 converted[index++] = whitespace[i];
2345 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002346#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002347 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002348 start_col++;
2349 } else {
2350 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002351
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002352#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002353 /* If buf contains an invalid multibyte non-control
2354 * character, interpret that character as though it's a
2355 * normal non-control character. */
David Lawrence Ramsey7a4aaa52005-06-16 02:09:57 +00002356 if (ISSET(USE_UTF8) && bad_char) {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002357 char *bad_buf_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002358 int bad_buf_mb_len;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002359
David Lawrence Ramsey4c6956b2005-01-12 04:32:43 +00002360 bad_buf_mb = make_mbchar((unsigned char)*buf_mb,
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002361 &bad_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002362
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002363 for (i = 0; i < bad_buf_mb_len; i++)
2364 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002365
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002366 start_col += mbwidth(bad_buf_mb);
2367
2368 free(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002369 } else {
2370#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002371 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002372 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002373
2374 start_col += mbwidth(buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002375#ifdef NANO_WIDE
2376 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002377#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002378 }
2379
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002380 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002381 }
2382
David Lawrence Ramsey6a0d5b82005-06-13 14:00:22 +00002383 free(buf_mb);
2384
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002385 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002386 converted[index] = '\0';
2387
2388 /* Make sure converted takes up no more than len columns. */
2389 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002390 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002391
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002392 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002393}
2394
Chris Allegretta7662c862003-01-13 01:35:15 +00002395/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002396 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002397 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002398 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002399 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002400void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002401{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002402 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002403 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002404
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002405 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002406
Chris Allegrettab3655b42001-10-22 03:15:31 +00002407 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002408 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002409
Chris Allegretta6df90f52002-07-19 01:08:59 +00002410 mvwaddstr(bottomwin, 0, 0, buf);
2411 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002412
2413 if (COLS > 1)
2414 waddch(bottomwin, x_real < wid ? ' ' : '$');
2415 if (COLS > 2) {
2416 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002417 char *expanded = display_string(inputbuf, page_start, wid,
2418 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002419
2420 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002421 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002422
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002423 waddstr(bottomwin, expanded);
2424 free(expanded);
2425 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2426 } else
2427 wmove(bottomwin, 0, COLS - 1);
David Lawrence Ramseyd37f6a32005-03-26 20:41:36 +00002428
Chris Allegrettab3655b42001-10-22 03:15:31 +00002429 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002430}
2431
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002432/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002433 * statusq(). */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002434int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002435#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002436 filestruct **history_list,
Chris Allegretta5beed502003-01-05 20:41:21 +00002437#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002438 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002439#ifndef DISABLE_TABCOMP
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002440 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002441#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002442 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002443{
2444 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002445 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002446 size_t curranswer_len;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002447#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002448 bool tabbed = FALSE;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002449 /* Whether we've pressed Tab. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002450#endif
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002451#ifndef NANO_SMALL
2452 char *history = NULL;
2453 /* The current history string. */
2454 char *magichistory = NULL;
2455 /* The temporary string typed at the bottom of the history, if
2456 * any. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002457#ifndef DISABLE_TABCOMP
David Lawrence Ramseyd922f192005-06-02 19:50:18 +00002458 int last_kbinput = ERR;
2459 /* The key we pressed before the current key. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002460 size_t complete_len = 0;
2461 /* The length of the original string that we're trying to
2462 * tab complete, if any. */
2463#endif
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002464#endif /* !NANO_SMALL */
Chris Allegretta09fc4302003-01-16 22:16:38 +00002465
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002466 answer = mallocstrcpy(answer, curranswer);
David Lawrence Ramsey0e0fef02005-05-26 18:05:22 +00002467 curranswer_len = strlen(answer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002468
David Lawrence Ramsey045d1302005-05-26 05:27:19 +00002469 /* Only put statusbar_x at the end of the string if it's
2470 * uninitialized, if it would be past the end of curranswer, or if
2471 * resetstatuspos is TRUE. Otherwise, leave it alone. This is so
2472 * the cursor position stays at the same place if a prompt-changing
2473 * toggle is pressed. */
2474 if (statusbar_x == (size_t)-1 || statusbar_x > curranswer_len ||
2475 resetstatuspos)
2476 statusbar_x = curranswer_len;
2477
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002478 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002479
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002480 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002481
David Lawrence Ramsey10f880c2005-04-29 03:24:43 +00002482 /* Refresh the edit window and the statusbar before getting
2483 * input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002484 wnoutrefresh(edit);
2485 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002486
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002487 /* If we're using restricted mode, we aren't allowed to change the
2488 * name of a file once it has one because that would allow writing
2489 * to files not specified on the command line. In this case,
2490 * disable all keys that would change the text if the filename isn't
2491 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002492 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002493 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002494 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002495
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002496 assert(statusbar_x <= strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002497
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002498#ifndef DISABLE_TABCOMP
David Lawrence Ramsey22425a22005-04-16 15:57:19 +00002499 if (kbinput != NANO_TAB_KEY)
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002500 tabbed = FALSE;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002501#endif
Chris Allegretta04d848e2000-11-05 17:54:41 +00002502
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002503 switch (kbinput) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002504 case NANO_TAB_KEY:
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002505#ifndef DISABLE_TABCOMP
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002506#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002507 if (history_list != NULL) {
2508 if (last_kbinput != NANO_TAB_KEY)
2509 complete_len = strlen(answer);
2510
2511 if (complete_len > 0) {
2512 answer = mallocstrcpy(answer,
2513 get_history_completion(history_list,
2514 answer, complete_len));
2515 statusbar_x = strlen(answer);
2516 }
2517 } else
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002518#endif /* !NANO_SMALL */
David Lawrence Ramseye2ce2792005-05-26 05:33:57 +00002519 if (allow_tabs)
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002520 answer = input_tab(answer, &statusbar_x, &tabbed,
2521 list);
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002522#endif /* !DISABLE_TABCOMP */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002523 break;
2524 case NANO_PREVLINE_KEY:
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002525#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002526 if (history_list != NULL) {
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002527 /* If we're scrolling up at the bottom of the
2528 * history list, answer isn't blank, and
2529 * magichistory isn't set, save answer in
2530 * magichistory. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002531 if ((*history_list)->next == NULL &&
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002532 answer[0] != '\0' && magichistory == NULL)
2533 magichistory = mallocstrcpy(NULL, answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002534
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002535 /* Get the older search from the history list and
2536 * save it in answer. If there is no older search,
2537 * don't do anything. */
2538 if ((history =
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002539 get_history_older(history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002540 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002541 statusbar_x = strlen(answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002542 }
David Lawrence Ramsey75f4b7c2005-05-03 21:35:58 +00002543
2544 /* This key has a shortcut list entry when it's used
2545 * to move to an older search, which means that
2546 * finished has been set to TRUE. Set it back to
2547 * FALSE here, so that we aren't kicked out of the
2548 * statusbar prompt. */
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002549 finished = FALSE;
Chris Allegretta5beed502003-01-05 20:41:21 +00002550 }
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002551#endif /* !NANO_SMALL */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002552 break;
2553 case NANO_NEXTLINE_KEY:
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002554#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002555 if (history_list != NULL) {
2556 /* Get the newer search from the history list and
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002557 * save it in answer. If there is no newer search,
2558 * don't do anything. */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002559 if ((history =
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002560 get_history_newer(history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002561 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002562 statusbar_x = strlen(answer);
Chris Allegrettac30fc242003-08-11 00:32:45 +00002563 }
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002564
2565 /* If, after scrolling down, we're at the bottom of
2566 * the history list, answer is blank, and
2567 * magichistory is set, save magichistory in
2568 * answer. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002569 if ((*history_list)->next == NULL &&
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002570 answer[0] == '\0' && magichistory != NULL) {
2571 answer = mallocstrcpy(answer, magichistory);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002572 statusbar_x = strlen(answer);
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002573 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002574 }
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002575#endif /* !NANO_SMALL */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002576 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002577 }
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002578
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002579 /* If we have a shortcut with an associated function, break out
2580 * if we're finished after running or trying to run the
2581 * function. */
2582 if (finished)
2583 break;
2584
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002585#if !defined(NANO_SMALL) && !defined(DISABLE_TABCOMP)
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002586 last_kbinput = kbinput;
2587#endif
2588
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002589 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002590 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002591 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002592
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002593#ifndef NANO_SMALL
David Lawrence Ramsey8234f672005-06-02 02:32:39 +00002594 /* Free magichistory if we need to. */
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002595 if (magichistory != NULL)
2596 free(magichistory);
2597#endif
2598
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002599 /* We finished putting in an answer or ran a normal shortcut's
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002600 * associated function, so reset statusbar_x. */
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002601 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002602 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002603 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002604
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002605 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002606}
2607
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002608/* Ask a question on the statusbar. Answer will be stored in answer
2609 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002610 * otherwise, the valid shortcut key caught. curranswer is any editable
2611 * text that we want to put up by default.
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002612 *
David Lawrence Ramsey67e3b932005-05-23 18:49:28 +00002613 * The allow_tabs parameter indicates whether we should allow tabs to be
2614 * interpreted. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002615int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002616#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002617 filestruct **history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002618#endif
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002619 const char *msg, ...)
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002620{
2621 va_list ap;
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002622 char *foo = charalloc(((COLS - 4) * mb_cur_max()) + 1);
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002623 int retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002624#ifndef DISABLE_TABCOMP
2625 bool list = FALSE;
2626#endif
2627
2628 bottombars(s);
2629
2630 va_start(ap, msg);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002631 vsnprintf(foo, (COLS - 4) * mb_cur_max(), msg, ap);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002632 va_end(ap);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002633 null_at(&foo, actual_x(foo, COLS - 4));
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002634
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002635 retval = nanogetstr(allow_tabs, foo, curranswer,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002636#ifndef NANO_SMALL
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002637 history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002638#endif
2639 s
2640#ifndef DISABLE_TABCOMP
2641 , &list
2642#endif
2643 );
2644 free(foo);
2645 resetstatuspos = FALSE;
2646
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002647 switch (retval) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002648 case NANO_CANCEL_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002649 retval = -1;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002650 resetstatuspos = TRUE;
2651 break;
2652 case NANO_ENTER_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002653 retval = (answer[0] == '\0') ? -2 : 0;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002654 resetstatuspos = TRUE;
2655 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002656 }
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002657
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002658 blank_statusbar();
2659
2660#ifdef DEBUG
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002661 fprintf(stderr, "answer = \"%s\"\n", answer);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002662#endif
2663
2664#ifndef DISABLE_TABCOMP
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002665 /* 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 * that they're cleared off. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002668 if (list)
2669 edit_refresh();
2670#endif
2671
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002672 return retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002673}
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);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002706 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002707
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002708 if (COLS <= 5 || COLS - 5 < verlen)
2709 space = 0;
2710 else {
2711 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002712 /* Reserve 2/3 of the screen plus one column for after the
2713 * version message. */
2714 if (space < COLS - (COLS / 3) + 1)
2715 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002716 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002717
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002718 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002719 /* The version message should only take up 1/3 of the screen
2720 * minus one column. */
2721 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002722 waddstr(topwin, " ");
2723 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002724
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002725 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002726 state = _("Modified");
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002727 else if (ISSET(VIEW_MODE))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002728 state = _("View");
2729 else {
2730 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002731 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002732 state = &hblank[COLS - statelen];
2733 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002734 statelen = strnlenpt(state, COLS);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002735
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);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002741
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002742 if (space == 0 || statelen >= space)
2743 goto the_end;
2744
2745#ifndef DISABLE_BROWSER
2746 if (path != NULL)
2747 prefix = _("DIR:");
2748 else
2749#endif
2750 if (filename[0] == '\0') {
2751 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002752 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002753 } else
2754 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002755
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002756 assert(statelen < space);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002757
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002758 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002759
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002760 /* If newfie is FALSE, we need a space after prefix. */
2761 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002762 prefixlen++;
2763
2764 if (path == NULL)
2765 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002766 if (space >= prefixlen + statelen)
2767 space -= prefixlen + statelen;
2768 else
2769 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002770 /* space is now the room we have for the file name. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002771
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002772 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002773 size_t lenpt = strlenpt(path), start_col;
2774
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002775 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002776
2777 if (dots) {
2778 start_col = lenpt - space + 3;
2779 space -= 3;
2780 } else
2781 start_col = 0;
2782
2783 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002784 }
2785
2786 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002787 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2788 /* The length of the expanded filename. */
2789
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002790 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002791 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002792 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002793 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002794 assert(strlenpt(prefix) + 1 == prefixlen);
2795
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002796 waddch(topwin, ' ');
2797 waddstr(topwin, exppath);
2798 }
2799 } else {
2800 /* We will say something like "File: ...ename". */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002801 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002802 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002803 goto the_end;
2804 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002805 waddnstr(topwin, "...", space + 3);
2806 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002807 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002808 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002809 }
2810
2811 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002812 free(exppath);
2813
2814 if (COLS <= 1 || statelen >= COLS - 1)
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002815 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002816 else {
2817 assert(COLS - statelen - 2 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002818
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002819 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002820 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
2821 actual_x(state, statelen));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002822 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002823
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002824 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002825
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002826 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002827 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002828 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002829}
2830
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002831/* If modified is not already set, set it and update titlebar. */
2832void set_modified(void)
2833{
2834 if (!ISSET(MODIFIED)) {
2835 SET(MODIFIED);
2836 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002837 }
2838}
2839
2840void statusbar(const char *msg, ...)
2841{
2842 va_list ap;
2843
2844 va_start(ap, msg);
2845
2846 /* Curses mode is turned off. If we use wmove() now, it will muck
2847 * up the terminal settings. So we just use vfprintf(). */
2848 if (curses_ended) {
2849 vfprintf(stderr, msg, ap);
2850 va_end(ap);
2851 return;
2852 }
2853
2854 /* Blank out the line. */
2855 blank_statusbar();
2856
2857 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002858 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002859 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002860#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002861 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002862
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002863 UNSET(WHITESPACE_DISPLAY);
2864#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002865 bar = charalloc(mb_cur_max() * (COLS - 3));
2866 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002867 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002868 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002869#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2870 if (old_whitespace)
2871 SET(WHITESPACE_DISPLAY);
2872#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002873 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002874 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002875 start_x = (COLS - foo_len - 4) / 2;
2876
2877 wmove(bottomwin, 0, start_x);
2878 wattron(bottomwin, A_REVERSE);
2879
2880 waddstr(bottomwin, "[ ");
2881 waddstr(bottomwin, foo);
2882 free(foo);
2883 waddstr(bottomwin, " ]");
2884 wattroff(bottomwin, A_REVERSE);
2885 wnoutrefresh(bottomwin);
2886 reset_cursor();
2887 wrefresh(edit);
2888 /* Leave the cursor at its position in the edit window, not
2889 * in the statusbar. */
2890 }
2891
2892 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002893 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002894}
2895
Chris Allegretta6232d662002-05-12 19:52:15 +00002896void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002897{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002898 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002899
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002900 if (ISSET(NO_HELP))
2901 return;
2902
Chris Allegretta6232d662002-05-12 19:52:15 +00002903 if (s == main_list) {
2904 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002905
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002906 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002907 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002908 slen = length_of_list(s);
2909
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002910 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002911 if (slen > MAIN_VISIBLE)
2912 slen = MAIN_VISIBLE;
2913 }
2914
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002915 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002916 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002917 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002918
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002919 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002920
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002921 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002922 const char *keystr;
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002923 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002924
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002925 /* Yucky sentinel values that we can't handle a better way. */
2926 if (s->ctrlval == NANO_CONTROL_SPACE)
2927 strcpy(foo, "^ ");
2928 else if (s->ctrlval == NANO_CONTROL_8)
2929 strcpy(foo, "^?");
2930 /* Normal values. Assume that the shortcut has an equivalent
2931 * control key, meta key sequence, or both. */
2932 else if (s->ctrlval != NANO_NO_KEY)
2933 sprintf(foo, "^%c", s->ctrlval + 64);
2934 else if (s->metaval != NANO_NO_KEY)
2935 sprintf(foo, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00002936
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002937 keystr = foo;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002938
2939 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002940 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002941 }
2942
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002943 wnoutrefresh(bottomwin);
2944 reset_cursor();
2945 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002946}
2947
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002948/* Write a shortcut key to the help area at the bottom of the window.
2949 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2950 * to write at most len characters, even if len is very small and
2951 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2952 * the whole string! We do not bother padding the entry with blanks. */
2953void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002954{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002955 size_t keystroke_len = strlenpt(keystroke) + 1;
2956
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002957 assert(keystroke != NULL && desc != NULL);
2958
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002959 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002960 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002961 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002962
2963 if (len > keystroke_len)
2964 len -= keystroke_len;
2965 else
2966 len = 0;
2967
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002968 if (len > 0) {
2969 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002970 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002971 }
2972}
2973
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002974/* nano scrolls horizontally within a line in chunks. This function
2975 * returns the column number of the first character displayed in the
2976 * window when the cursor is at the given column. Note that
2977 * 0 <= column - get_page_start(column) < COLS. */
2978size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002979{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002980 assert(COLS > 0);
2981 if (column == 0 || column < COLS - 1)
2982 return 0;
2983 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002984 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002985 else if (COLS > 2)
2986 return column - (COLS - 2);
2987 else
2988 return column - (COLS - 1);
2989 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002990}
2991
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002992/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002993 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002994void reset_cursor(void)
2995{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002996 /* If we haven't opened any files yet, put the cursor in the top
2997 * left corner of the edit window and get out. */
2998 if (edittop == NULL || current == NULL) {
2999 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003000 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003001 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003002
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003003 current_y = current->lineno - edittop->lineno;
3004 if (current_y < editwinrows) {
3005 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003006 wmove(edit, current_y, x - get_page_start(x));
3007 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003008}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003009
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003010/* edit_add() takes care of the job of actually painting a line into the
3011 * edit window. fileptr is the line to be painted, at row yval of the
3012 * window. converted is the actual string to be written to the window,
3013 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003014 * characters. start is the column number of the first character of
3015 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003016 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003017void edit_add(const filestruct *fileptr, const char *converted, int
3018 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003019{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003020#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003021 size_t startpos = actual_x(fileptr->data, start);
3022 /* The position in fileptr->data of the leftmost character
3023 * that displays at least partially on the window. */
3024 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3025 /* The position in fileptr->data of the first character that is
3026 * completely off the window to the right.
3027 *
3028 * Note that endpos might be beyond the null terminator of the
3029 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003030#endif
3031
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003032 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003033 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003034
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003035 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003036 * just the text that needs it). */
3037 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003038
Chris Allegretta7dd77682001-12-08 19:52:28 +00003039#ifdef ENABLE_COLOR
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003040 if (colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003041 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003042
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003043 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3044 int x_start;
3045 /* Starting column for mvwaddnstr. Zero-based. */
3046 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003047 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003048 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003049 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003050 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003051 regmatch_t startmatch; /* match position for start_regexp */
3052 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003053
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003054 if (tmpcolor->bright)
3055 wattron(edit, A_BOLD);
3056 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003057 /* Two notes about regexec(). Return value 0 means there is
3058 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003059 * after the match. */
3060
3061 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003062 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003063 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003064
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003065 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003066 * last match. Even though two matches may overlap, we
3067 * want to ignore them, so that we can highlight
3068 * C-strings correctly. */
3069 while (k < endpos) {
3070 /* Note the fifth parameter to regexec(). It says
3071 * not to match the beginning-of-line character
3072 * unless k is 0. If regexec() returns REG_NOMATCH,
3073 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003074 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003075 &startmatch, (k == 0) ? 0 :
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003076 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003077 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003078 /* Translate the match to the beginning of the
3079 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003080 startmatch.rm_so += k;
3081 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003082 if (startmatch.rm_so == startmatch.rm_eo) {
3083 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003084 statusbar(
3085 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003086 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003087 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003088 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003089 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003090 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003091 x_start = strnlenpt(fileptr->data,
3092 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003093
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003094 index = actual_x(converted, x_start);
3095
3096 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003097 strnlenpt(fileptr->data,
3098 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003099
3100 assert(0 <= x_start && 0 <= paintlen);
3101
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003102 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003103 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003104 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003105 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003106 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003107 } else {
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003108 /* This is a multi-line regexp. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003109 * First, we have to see if the beginning of the line is
3110 * colored by a start on an earlier line, and an end on
3111 * this line or later.
3112 *
3113 * We find the first line before fileptr matching the
3114 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003115 * end, then go to step two. Otherwise, find the next
3116 * line after start_line matching the end. If that line
3117 * is not before fileptr, then paint the beginning of
3118 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003119 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003120 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003121 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003122 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003123 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003124
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003125 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003126 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003127 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003128 /* If there is an end on this line, there is no need
3129 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003130 if (regexec(tmpcolor->end, start_line->data, 0,
3131 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003132 goto step_two;
3133 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003134 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003135 /* No start found, so skip to the next step. */
3136 if (start_line == NULL)
3137 goto step_two;
3138 /* Now start_line is the first line before fileptr
3139 * containing a start match. Is there a start on this
3140 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003141 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003142 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003143 start_col += startmatch.rm_so;
3144 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003145 if (regexec(tmpcolor->end, start_line->data +
3146 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003147 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003148 REG_NOTBOL) == REG_NOMATCH)
3149 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003150 break;
3151 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003152 if (regexec(&tmpcolor->start, start_line->data +
3153 start_col, 1, &startmatch,
3154 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003155 /* No later start on this line. */
3156 goto step_two;
3157 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003158 /* Indeed, there is a start not followed on this line by
3159 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003160
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003161 /* We have already checked that there is no end before
3162 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003163 * the start at all? We don't paint unterminated
3164 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003165 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003166 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003167 regexec(tmpcolor->end, end_line->data, 1,
3168 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003169 end_line = end_line->next;
3170
3171 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003172 if (end_line == NULL || (end_line == fileptr &&
3173 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003174 goto step_two;
3175
3176 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003177 if (end_line != fileptr)
3178 /* If the start of fileptr is on a different line
3179 * from the end, paintlen is -1, meaning that
3180 * everything on the line gets painted. */
3181 paintlen = -1;
3182 else
3183 /* Otherwise, paintlen is the expanded location of
3184 * the end of the match minus the expanded location
3185 * of the beginning of the page. */
3186 paintlen = actual_x(converted,
3187 strnlenpt(fileptr->data, endmatch.rm_eo) -
3188 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003189
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003190 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003191
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003192 step_two:
3193 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003194 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003195
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003196 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003197 if (regexec(&tmpcolor->start,
3198 fileptr->data + start_col, 1, &startmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003199 (start_col == 0) ? 0 :
3200 REG_NOTBOL) == REG_NOMATCH ||
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003201 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003202 /* No more starts on this line. */
3203 break;
3204 /* Translate the match to be relative to the
3205 * beginning of the line. */
3206 startmatch.rm_so += start_col;
3207 startmatch.rm_eo += start_col;
3208
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003209 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003210 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003211 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003212 x_start = strnlenpt(fileptr->data,
3213 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003214
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003215 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003216
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003217 if (regexec(tmpcolor->end,
3218 fileptr->data + startmatch.rm_eo, 1, &endmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003219 (startmatch.rm_eo == 0) ? 0 :
3220 REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003221 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003222 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003223 endmatch.rm_so += startmatch.rm_eo;
3224 endmatch.rm_eo += startmatch.rm_eo;
3225 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003226 * appear on this page, and is the match more
3227 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003228 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003229 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003230 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003231 strnlenpt(fileptr->data,
3232 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003233
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003234 assert(0 <= x_start && x_start < COLS);
3235
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003236 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003237 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003238 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003239 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003240 /* There is no end on this line. But we haven't
3241 * yet looked for one on later lines. */
3242 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003243
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003244 while (end_line != NULL &&
3245 regexec(tmpcolor->end, end_line->data,
3246 0, NULL, 0) == REG_NOMATCH)
3247 end_line = end_line->next;
3248
3249 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003250 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003251
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003252 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003253 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003254 /* We painted to the end of the line, so
3255 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003256 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003257 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003258 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003259 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003260 }
3261 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003262
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003263 wattroff(edit, A_BOLD);
3264 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003265 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003266 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003267#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003268
Chris Allegretta7dd77682001-12-08 19:52:28 +00003269#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003270 if (ISSET(MARK_ISSET)
3271 && (fileptr->lineno <= mark_beginbuf->lineno
3272 || fileptr->lineno <= current->lineno)
3273 && (fileptr->lineno >= mark_beginbuf->lineno
3274 || fileptr->lineno >= current->lineno)) {
3275 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003276
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003277 const filestruct *top;
3278 /* Either current or mark_beginbuf, whichever is first. */
3279 size_t top_x;
3280 /* current_x or mark_beginx, corresponding to top. */
3281 const filestruct *bot;
3282 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003283 int x_start;
3284 /* Starting column for mvwaddnstr. Zero-based. */
3285 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003286 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003287 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003288 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003289 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003290
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003291 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003292
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003293 if (top->lineno < fileptr->lineno || top_x < startpos)
3294 top_x = startpos;
3295 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3296 bot_x = endpos;
3297
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003298 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003299 if (top_x < endpos && bot_x > startpos) {
3300 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003301
3302 /* x_start is the expanded location of the beginning of the
3303 * mark minus the beginning of the page. */
3304 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003305
3306 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003307 /* If the end of the mark is off the page, paintlen is
3308 * -1, meaning that everything on the line gets
3309 * painted. */
3310 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003311 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003312 /* Otherwise, paintlen is the expanded location of the
3313 * end of the mark minus the expanded location of the
3314 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003315 paintlen = strnlenpt(fileptr->data, bot_x) -
3316 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003317
3318 /* If x_start is before the beginning of the page, shift
3319 * paintlen x_start characters to compensate, and put
3320 * x_start at the beginning of the page. */
3321 if (x_start < 0) {
3322 paintlen += x_start;
3323 x_start = 0;
3324 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003325
3326 assert(x_start >= 0 && x_start <= strlen(converted));
3327
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003328 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003329
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003330 if (paintlen > 0)
3331 paintlen = actual_x(converted + index, paintlen);
3332
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003333 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003334 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003335 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003336 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003337 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003338 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003339#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003340}
3341
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003342/* Just update one line in the edit buffer. This is basically a wrapper
3343 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003344 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003345 * If fileptr != current, then index is considered 0. The line will be
3346 * displayed starting with fileptr->data[index]. Likely args are
3347 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003348void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003349{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003350 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003351 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003352 char *converted;
3353 /* fileptr->data converted to have tabs and control characters
3354 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003355 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003356
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003357 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003358
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003359 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003360
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003361 /* We assume the line numbers are valid. Is that really true? */
3362 assert(line < 0 || line == check_linenumbers(fileptr));
3363
3364 if (line < 0 || line >= editwinrows)
3365 return;
3366
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003367 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003368 mvwaddstr(edit, line, 0, hblank);
3369
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003370 /* Next, convert variables that index the line to their equivalent
3371 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003372 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003373 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003374
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003375 /* Expand the line, replacing tabs with spaces, and control
3376 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003377 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003378
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003379 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003380 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003381 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003382
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003383 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003384 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003385 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003386 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003387}
3388
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003389/* Return a nonzero value if we need an update after moving
3390 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003391 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003392int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003393{
3394 return
3395#ifndef NANO_SMALL
3396 ISSET(MARK_ISSET) ||
3397#endif
3398 get_page_start(old_pww) != get_page_start(placewewant);
3399}
3400
3401/* Return a nonzero value if we need an update after moving vertically.
3402 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003403 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003404int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003405{
3406 return
3407#ifndef NANO_SMALL
3408 ISSET(MARK_ISSET) ||
3409#endif
3410 get_page_start(old_pww) != get_page_start(placewewant);
3411}
3412
3413/* Scroll the edit window in the given direction and the given number
3414 * of lines, and draw new lines on the blank lines left after the
3415 * scrolling. direction is the direction to scroll, either UP or DOWN,
3416 * and nlines is the number of lines to scroll. Don't redraw the old
3417 * topmost or bottommost line (where we assume current is) before
3418 * scrolling or draw the new topmost or bottommost line after scrolling
3419 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003420 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003421void edit_scroll(updown direction, int nlines)
3422{
3423 filestruct *foo;
3424 int i, scroll_rows = 0;
3425
3426 /* Scrolling less than one line or more than editwinrows lines is
3427 * redundant, so don't allow it. */
3428 if (nlines < 1 || nlines > editwinrows)
3429 return;
3430
3431 /* Move the top line of the edit window up or down (depending on the
3432 * value of direction) nlines lines. If there are fewer lines of
3433 * text than that left, move it to the top or bottom line of the
3434 * file (depending on the value of direction). Keep track of
3435 * how many lines we moved in scroll_rows. */
3436 for (i = nlines; i > 0; i--) {
3437 if (direction == UP) {
3438 if (edittop->prev == NULL)
3439 break;
3440 edittop = edittop->prev;
3441 scroll_rows--;
3442 } else {
3443 if (edittop->next == NULL)
3444 break;
3445 edittop = edittop->next;
3446 scroll_rows++;
3447 }
3448 }
3449
3450 /* Scroll the text on the screen up or down scroll_rows lines,
3451 * depending on the value of direction. */
3452 scrollok(edit, TRUE);
3453 wscrl(edit, scroll_rows);
3454 scrollok(edit, FALSE);
3455
3456 foo = edittop;
3457 if (direction != UP) {
3458 int slines = editwinrows - nlines;
3459 for (; slines > 0 && foo != NULL; slines--)
3460 foo = foo->next;
3461 }
3462
3463 /* And draw new lines on the blank top or bottom lines of the edit
3464 * window, depending on the value of direction. Don't draw the new
3465 * topmost or new bottommost line. */
3466 while (scroll_rows != 0 && foo != NULL) {
3467 if (foo->next != NULL)
3468 update_line(foo, 0);
3469 if (direction == UP)
3470 scroll_rows++;
3471 else
3472 scroll_rows--;
3473 foo = foo->next;
3474 }
3475}
3476
3477/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003478 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003479void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003480{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003481 int do_refresh = need_vertical_update(0) ||
3482 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003483 const filestruct *foo;
3484
3485 /* If either old_current or current is offscreen, refresh the screen
3486 * and get out. */
3487 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3488 edittop->lineno + editwinrows || current->lineno <
3489 edittop->lineno || current->lineno >= edittop->lineno +
3490 editwinrows) {
3491 edit_refresh();
3492 return;
3493 }
3494
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003495 /* Update old_current and current if we're not on the first page
3496 * and/or we're not on the same page as before. If the mark is on,
3497 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003498 foo = old_current;
3499 while (foo != current) {
3500 if (do_refresh)
3501 update_line(foo, 0);
3502#ifndef NANO_SMALL
3503 if (!ISSET(MARK_ISSET))
3504#endif
3505 break;
3506 if (foo->lineno > current->lineno)
3507 foo = foo->prev;
3508 else
3509 foo = foo->next;
3510 }
3511 if (do_refresh)
3512 update_line(current, current_x);
3513}
3514
Chris Allegretta6df90f52002-07-19 01:08:59 +00003515/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003516void edit_refresh(void)
3517{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003518 if (current->lineno < edittop->lineno ||
3519 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003520 /* Note that edit_update() changes edittop so that it's in range
3521 * of current. Thus, when it then calls edit_refresh(), there
3522 * is no danger of getting an infinite loop. */
3523 edit_update(
3524#ifndef NANO_SMALL
David Lawrence Ramseyb2b69762005-06-16 02:13:10 +00003525 ISSET(SMOOTH_SCROLL) ? NONE :
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003526#endif
3527 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003528 else {
3529 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003530 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003531
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003532#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003533 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003534#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003535
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003536 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003537 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003538 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003539 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003540 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003541 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003542 }
3543 while (nlines < editwinrows) {
3544 mvwaddstr(edit, nlines, 0, hblank);
3545 nlines++;
3546 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003547 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003548 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003549 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003550}
3551
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003552/* A nice generic routine to update the edit buffer. We keep current in
3553 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003554void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003555{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003556 filestruct *foo = current;
3557
Chris Allegretta6df90f52002-07-19 01:08:59 +00003558 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003559 /* If location is CENTER, we move edittop up (editwinrows / 2)
3560 * lines. This puts current at the center of the screen. If
3561 * location is NONE, we move edittop up current_y lines if
3562 * current_y is in range of the screen, 0 lines if current_y is
3563 * less than 0, or (editwinrows - 1) lines if current_y is
3564 * greater than (editwinrows - 1). This puts current at the
3565 * same place on the screen as before, or at the top or bottom
3566 * of the screen if edittop is beyond either. */
3567 int goal;
3568
3569 if (location == CENTER)
3570 goal = editwinrows / 2;
3571 else {
3572 goal = current_y;
3573
3574 /* Limit goal to (editwinrows - 1) lines maximum. */
3575 if (goal > editwinrows - 1)
3576 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003577 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003578
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003579 for (; goal > 0 && foo->prev != NULL; goal--)
3580 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003581 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003582
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003583 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003584 edit_refresh();
3585}
3586
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003587/* Ask a simple yes/no question, specified in msg, on the statusbar.
3588 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3589 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003590int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003591{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003592 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003593 const char *yesstr; /* String of yes characters accepted. */
3594 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003595 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003596
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003597 /* yesstr, nostr, and allstr are strings of any length. Each string
David Lawrence Ramseydcb4e3a2005-04-08 20:27:02 +00003598 * consists of all single-byte characters accepted as valid
3599 * characters for that value. The first value will be the one
3600 * displayed in the shortcuts. Translators: if possible, specify
3601 * both the shortcuts for your language and English. For example,
3602 * in French: "OoYy" for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003603 yesstr = _("Yy");
3604 nostr = _("Nn");
3605 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003606
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003607 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003608 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003609
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003610 if (COLS < 32)
3611 width = COLS / 2;
3612
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003613 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003614 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003615
Chris Allegretta6232d662002-05-12 19:52:15 +00003616 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003617 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003618 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003619
3620 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003621 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003622 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003623 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003624 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003625
Chris Allegrettadb28e962003-01-28 01:23:40 +00003626 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003627 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003628 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003629
Chris Allegrettadb28e962003-01-28 01:23:40 +00003630 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003631 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003632 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003633
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003634 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003635
3636 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003637 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003638
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003639 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003640
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003641 wrefresh(bottomwin);
3642
Chris Allegrettadb28e962003-01-28 01:23:40 +00003643 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003644 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003645 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003646#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003647 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003648#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003649
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003650 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003651
David Lawrence Ramseyda331532005-06-06 17:00:08 +00003652 if (kbinput == NANO_REFRESH_KEY) {
3653 total_update();
3654 continue;
3655 } else if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003656 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003657#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003658 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003659 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003660
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003661 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003662 wenclose(bottomwin, mouse_y, mouse_x) &&
3663 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003664 int x = mouse_x / width;
3665 /* Did we click in the first column of shortcuts, or
3666 * the second? */
3667 int y = mouse_y - editwinrows - 3;
3668 /* Did we click in the first row of shortcuts? */
3669
3670 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3671
3672 /* x = 0 means they clicked Yes or No.
3673 * y = 0 means Yes or All. */
3674 ok = -2 * x * y + x - y + 1;
3675
3676 if (ok == 2 && !all)
3677 ok = -2;
3678 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003679 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003680#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003681 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003682 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003683 else if (strchr(yesstr, kbinput) != NULL)
3684 ok = 1;
3685 else if (strchr(nostr, kbinput) != NULL)
3686 ok = 0;
3687 else if (all && strchr(allstr, kbinput) != NULL)
3688 ok = 2;
3689 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003690
Chris Allegrettadb28e962003-01-28 01:23:40 +00003691 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003692}
3693
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003694void total_update(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003695{
David Lawrence Ramsey0bfec6e2005-04-25 20:08:29 +00003696 clearok(edit, TRUE);
3697 wrefresh(edit);
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003698}
3699
3700void total_refresh(void)
3701{
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003702 total_update();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003703 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003704 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003705 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003706}
3707
3708void display_main_list(void)
3709{
3710 bottombars(main_list);
3711}
3712
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003713/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3714 * display the cursor position. Otherwise, we display it only if the
3715 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003716 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003717 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3718 * old_i and old_totsize. That way, we leave the current statusbar
3719 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003720void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003721{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003722 char c;
3723 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003724 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003725 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003726
Chris Allegrettad26ab912003-01-28 01:16:47 +00003727 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003728
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003729 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003730 old_totsize = totsize;
3731
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003732 c = current->data[current_x];
3733 f = current->next;
3734 current->data[current_x] = '\0';
3735 current->next = NULL;
3736 get_totals(fileage, current, NULL, &i);
3737 current->data[current_x] = c;
3738 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003739
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003740 /* Check whether totsize is correct. Else there is a bug
3741 * somewhere. */
3742 assert(current != filebot || i == totsize);
3743
Chris Allegrettad26ab912003-01-28 01:16:47 +00003744 if (constant && ISSET(DISABLE_CURPOS)) {
3745 UNSET(DISABLE_CURPOS);
3746 old_i = i;
3747 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003748 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003749 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003750
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003751 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003752 * unconditionally; otherwise, only display the position when the
3753 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003754 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003755 size_t xpt = xplustabs() + 1;
3756 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003757 int linepct = 100 * current->lineno / totlines;
3758 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003759 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003760
3761 statusbar(
3762 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3763 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003764 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003765 (unsigned long)i, (unsigned long)totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003766 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003767 }
3768
3769 old_i = i;
3770 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003771}
3772
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003773void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003774{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003775 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003776}
3777
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003778#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003779/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003780size_t help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003781{
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003782 int help_cols = (COLS > 24) ? COLS - 8 : 24;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003783
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003784 /* Try to break the line at (COLS - 8) columns if we have more than
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003785 * 24 columns, and at 24 columns otherwise. */
David Lawrence Ramsey40e211b2005-03-19 21:15:30 +00003786 size_t retval = break_line(ptr, help_cols, TRUE);
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003787 size_t retval_save = retval;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003788
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003789 /* Get the length of the entire line up to a null or a newline. */
3790 while (*(ptr + retval) != '\0' && *(ptr + retval) != '\n')
3791 retval += move_mbright(ptr + retval, 0);
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003792
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003793 /* If the entire line doesn't go more than 8 columns beyond where we
3794 * tried to break it, we should display it as-is. Otherwise, we
3795 * should display it only up to the break. */
3796 if (strnlenpt(ptr, retval) > help_cols + 8)
3797 retval = retval_save;
3798
3799 return retval;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003800}
3801
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003802/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003803void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003804{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003805 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003806 /* The line number in help_text of the first displayed help
3807 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003808 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003809 /* no_more means the end of the help text is shown, so don't go
3810 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003811 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003812 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003813
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003814 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003815#ifndef DISABLE_MOUSE
3816 const shortcut *oldshortcut = currshortcut;
3817 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003818 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003819#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003820
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003821 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003822 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003823 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003824 blank_statusbar();
3825
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003826 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003827 help_init();
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003828
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003829 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003830
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003831#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003832 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003833 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003834 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003835#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003836
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003837 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003838 /* Make sure that the help screen's shortcut list will actually
3839 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003840 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003841 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003842 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003843
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003844 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003845
3846 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003847 int i;
3848 int old_line = line;
3849 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003850 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003851
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003852 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003853#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003854 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003855 {
3856 int mouse_x, mouse_y;
3857 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3858 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003859 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003860#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003861 case NANO_PREVPAGE_KEY:
3862 case NANO_PREVPAGE_FKEY:
3863 if (line > 0) {
3864 line -= editwinrows - 2;
3865 if (line < 0)
3866 line = 0;
3867 }
3868 break;
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003869 case NANO_NEXTPAGE_KEY:
3870 case NANO_NEXTPAGE_FKEY:
3871 if (!no_more)
3872 line += editwinrows - 2;
3873 break;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003874 case NANO_PREVLINE_KEY:
3875 if (line > 0)
3876 line--;
3877 break;
3878 case NANO_NEXTLINE_KEY:
3879 if (!no_more)
3880 line++;
3881 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003882 }
3883
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003884 if (kbinput == NANO_REFRESH_KEY)
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003885 total_update();
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003886 else {
3887 if (line == old_line && kbinput != ERR)
3888 goto skip_redisplay;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003889
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003890 blank_edit();
3891 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003892
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003893 /* Calculate where in the text we should be, based on the
3894 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003895 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003896 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003897 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003898 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003899 }
3900
Chris Allegretta4640fe32003-02-10 03:10:03 +00003901 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003902 size_t j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003903
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003904 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003905 ptr += j;
3906 if (*ptr == '\n')
3907 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003908 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003909 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003910
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003911 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003912 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003913 } while (kbinput != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003914
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003915#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003916 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003917#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003918
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003919 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003920 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003921 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003922 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003923 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003924 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003925 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003926
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003927 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003928 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003929
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003930 /* The help_init() at the beginning allocated help_text. Since
3931 * help_text has now been written to the screen, we don't need it
3932 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003933 free(help_text);
3934 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003935}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003936#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003937
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003938/* Highlight the current word being replaced or spell checked. We
3939 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003940void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003941{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003942 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003943 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003944
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003945 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003946 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003947 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003948
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003949 assert(y > 0);
3950
3951 if (word_len > y)
3952 y--;
3953
Chris Allegrettafb62f732000-12-05 11:36:41 +00003954 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003955
Chris Allegrettafb62f732000-12-05 11:36:41 +00003956 if (highlight_flag)
3957 wattron(edit, A_REVERSE);
3958
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003959#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003960 /* This is so we can show zero-length regexes. */
3961 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00003962 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003963 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003964#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003965 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003966
3967 if (word_len > y)
3968 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003969
3970 if (highlight_flag)
3971 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003972}
3973
David Lawrence Ramseycc814362005-06-05 19:08:59 +00003974#ifndef NDEBUG
3975/* Return what the current line number should be, starting at edittop
3976 * and ending at fileptr. */
3977int check_linenumbers(const filestruct *fileptr)
3978{
3979 int check_line = 0;
3980 const filestruct *filetmp;
3981
3982 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
3983 check_line++;
3984
3985 return check_line;
3986}
3987#endif
3988
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003989#ifdef DEBUG
David Lawrence Ramsey1e64db62005-06-14 23:38:41 +00003990/* Dump the filestruct inptr to stderr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003991void dump_buffer(const filestruct *inptr)
3992{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003993 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003994 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003995 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003996 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003997 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003998 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003999
4000 while (inptr != NULL) {
4001 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4002 inptr = inptr->next;
4003 }
4004}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004005
David Lawrence Ramsey1e64db62005-06-14 23:38:41 +00004006/* Dump the main filestruct to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004007void dump_buffer_reverse(void)
4008{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004009 const filestruct *fileptr = filebot;
4010
4011 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004012 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004013 fileptr = fileptr->prev;
4014 }
4015}
4016#endif /* DEBUG */
4017
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004018#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004019#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004020#define XLCREDIT_LEN 8
4021
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004022/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004023void do_credits(void)
4024{
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004025 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004026 const char *credits[CREDIT_LEN] = {
4027 NULL, /* "The nano text editor" */
4028 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004029 VERSION,
4030 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004031 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004032 "Chris Allegretta",
4033 "Jordi Mallach",
4034 "Adam Rogoyski",
4035 "Rob Siemborski",
4036 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004037 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004038 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004039 "Ken Tyler",
4040 "Sven Guckes",
David Lawrence Ramsey7bf86e12005-06-08 19:50:02 +00004041 "Florian K\xF6nig",
Chris Allegretta598106e2002-01-19 01:59:37 +00004042 "Pauli Virtanen",
4043 "Daniele Medri",
4044 "Clement Laforet",
4045 "Tedi Heriyanto",
4046 "Bill Soudan",
4047 "Christian Weisgerber",
4048 "Erik Andersen",
4049 "Big Gaute",
4050 "Joshua Jensen",
4051 "Ryan Krebs",
4052 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004053 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004054 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004055 "Plattsburgh State University",
4056 "Benet Laboratories",
4057 "Amy Allegretta",
4058 "Linda Young",
4059 "Jeremy Robichaud",
4060 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004061 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004062 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004063 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004064 "Thomas Dickey",
4065 "Pavel Curtis",
4066 "Zeyd Ben-Halim",
4067 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004068 NULL, /* "and anyone else we forgot..." */
4069 NULL, /* "Thank you for using nano!" */
4070 "",
4071 "",
4072 "",
4073 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004074 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004075 "",
4076 "",
4077 "",
4078 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004079 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004080 };
4081
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004082 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004083 N_("The nano text editor"),
4084 N_("version"),
4085 N_("Brought to you by:"),
4086 N_("Special thanks to:"),
4087 N_("The Free Software Foundation"),
4088 N_("For ncurses:"),
4089 N_("and anyone else we forgot..."),
4090 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004091 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004092
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004093 curs_set(0);
4094 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004095 scrollok(edit, TRUE);
4096 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004097 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004098 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004099 blank_statusbar();
4100 blank_bottombars();
4101 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004102 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004103 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004104
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004105 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004106 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004107 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004108
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004109 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004110 char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004111 size_t start_x;
4112
David Lawrence Ramsey631242d2005-03-15 07:06:54 +00004113 /* Make sure every credit is a valid multibyte string, since
4114 * we can't dynamically set the credits to their multibyte
4115 * equivalents when we need to. Sigh... */
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004116 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004117 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004118
4119 what = mallocstrcpy(NULL, _(xlcredits[xlpos]));
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004120 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004121 } else
David Lawrence Ramsey30d0a812005-06-13 14:50:32 +00004122 what = make_valid_mbstring(credits[crpos]);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004123
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004124 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004125 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
4126 start_x, what);
4127
4128 free(what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004129 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004130
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004131 napms(700);
4132 scroll(edit);
4133 wrefresh(edit);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004134 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004135 break;
4136 napms(700);
4137 scroll(edit);
4138 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004139 }
4140
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004141 if (kbinput != ERR)
4142 ungetch(kbinput);
4143
4144 curs_set(1);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004145 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004146 nodelay(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004147 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004148}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004149#endif