blob: 0b923fb5b7c19fe661b705c72d754d474d0a15f9 [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 Ramseyf0195a82005-03-14 18:47:21 +0000553 char *byte_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000554 int byte_mb_len, *seq, i;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000555
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
563 /* Put back the multibyte equivalent of the
564 * byte value. */
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +0000565 byte_mb = make_mbchar(byte, &byte_mb_len);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000566
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(seq);
576 free(byte_mb);
577 }
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 Ramseya593f532003-11-28 19:47:42 +00001514 /* Calculate the width of each shortcut in the list (it's the
1515 * same for all of them). */
1516 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. */
1920 if (!is_alnum_mbchar(char_mb))
1921 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. */
1936 if (is_alnum_mbchar(char_mb))
1937 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. */
1963 if (!is_alnum_mbchar(char_mb))
1964 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. */
1985 if (is_alnum_mbchar(char_mb))
1986 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. */
2008 if (!is_alnum_mbchar(char_mb))
2009 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 Ramseyb54155c2005-01-12 03:25:57 +00002257 /* Allocate enough space for the entire line. It should contain
2258 * (len + 2) multibyte characters at most. */
2259 alloc_len = mb_cur_max() * (len + 2);
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 Ramseyb54155c2005-01-12 03:25:57 +00002290 else if (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. */
2356 if (!ISSET(NO_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 Ramsey6d594a92005-01-05 21:43:43 +00002383 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002384 converted[index] = '\0';
2385
2386 /* Make sure converted takes up no more than len columns. */
2387 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002388 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002389
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002390 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002391}
2392
Chris Allegretta7662c862003-01-13 01:35:15 +00002393/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002394 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002395 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002396 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002397 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002398void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002399{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002400 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002401 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002402
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002403 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002404
Chris Allegrettab3655b42001-10-22 03:15:31 +00002405 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002406 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002407
Chris Allegretta6df90f52002-07-19 01:08:59 +00002408 mvwaddstr(bottomwin, 0, 0, buf);
2409 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002410
2411 if (COLS > 1)
2412 waddch(bottomwin, x_real < wid ? ' ' : '$');
2413 if (COLS > 2) {
2414 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002415 char *expanded = display_string(inputbuf, page_start, wid,
2416 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002417
2418 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002419 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002420
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002421 waddstr(bottomwin, expanded);
2422 free(expanded);
2423 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2424 } else
2425 wmove(bottomwin, 0, COLS - 1);
David Lawrence Ramseyd37f6a32005-03-26 20:41:36 +00002426
Chris Allegrettab3655b42001-10-22 03:15:31 +00002427 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002428}
2429
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002430/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002431 * statusq(). */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002432int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
Chris Allegretta5beed502003-01-05 20:41:21 +00002433#ifndef NANO_SMALL
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002434 filestruct *history_list,
Chris Allegretta5beed502003-01-05 20:41:21 +00002435#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002436 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002437#ifndef DISABLE_TABCOMP
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002438 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002439#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002440 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002441{
2442 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002443 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002444 size_t curranswer_len;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002445#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002446 bool tabbed = FALSE;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002447 /* Whether we've pressed Tab. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002448#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002449#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002450 char *history = NULL;
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002451 /* The current history string. */
2452 char *magichistory = NULL;
2453 /* The temporary string typed at the bottom of the history, if
2454 * any. */
Chris Allegretta5beed502003-01-05 20:41:21 +00002455#endif
Chris Allegretta09fc4302003-01-16 22:16:38 +00002456
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002457 answer = mallocstrcpy(answer, curranswer);
David Lawrence Ramsey0e0fef02005-05-26 18:05:22 +00002458 curranswer_len = strlen(answer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002459
David Lawrence Ramsey045d1302005-05-26 05:27:19 +00002460 /* Only put statusbar_x at the end of the string if it's
2461 * uninitialized, if it would be past the end of curranswer, or if
2462 * resetstatuspos is TRUE. Otherwise, leave it alone. This is so
2463 * the cursor position stays at the same place if a prompt-changing
2464 * toggle is pressed. */
2465 if (statusbar_x == (size_t)-1 || statusbar_x > curranswer_len ||
2466 resetstatuspos)
2467 statusbar_x = curranswer_len;
2468
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002469 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002470
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002471 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002472
David Lawrence Ramsey10f880c2005-04-29 03:24:43 +00002473 /* Refresh the edit window and the statusbar before getting
2474 * input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002475 wnoutrefresh(edit);
2476 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002477
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002478 /* If we're using restricted mode, we aren't allowed to change the
2479 * name of a file once it has one because that would allow writing
2480 * to files not specified on the command line. In this case,
2481 * disable all keys that would change the text if the filename isn't
2482 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002483 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002484 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002485 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002486
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002487 assert(statusbar_x <= strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002488
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002489#ifndef DISABLE_TABCOMP
David Lawrence Ramsey22425a22005-04-16 15:57:19 +00002490 if (kbinput != NANO_TAB_KEY)
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002491 tabbed = FALSE;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002492#endif
Chris Allegretta04d848e2000-11-05 17:54:41 +00002493
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002494 switch (kbinput) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002495 case NANO_TAB_KEY:
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002496#ifndef DISABLE_TABCOMP
David Lawrence Ramseye2ce2792005-05-26 05:33:57 +00002497 if (allow_tabs)
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002498 answer = input_tab(answer, &statusbar_x, &tabbed,
2499 list);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002500#endif
2501 break;
2502 case NANO_PREVLINE_KEY:
2503#ifndef NANO_SMALL
2504 if (history_list != NULL) {
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002505 /* If we're scrolling up at the bottom of the
2506 * history list, answer isn't blank, and
2507 * magichistory isn't set, save answer in
2508 * magichistory. */
2509 if (history_list->next == NULL &&
2510 answer[0] != '\0' && magichistory == NULL)
2511 magichistory = mallocstrcpy(NULL, answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002512
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002513 /* Get the older search from the history list and
2514 * save it in answer. If there is no older search,
2515 * don't do anything. */
2516 if ((history =
2517 get_history_older(&history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002518 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002519 statusbar_x = strlen(answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002520 }
David Lawrence Ramsey75f4b7c2005-05-03 21:35:58 +00002521
2522 /* This key has a shortcut list entry when it's used
2523 * to move to an older search, which means that
2524 * finished has been set to TRUE. Set it back to
2525 * FALSE here, so that we aren't kicked out of the
2526 * statusbar prompt. */
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002527 finished = FALSE;
Chris Allegretta5beed502003-01-05 20:41:21 +00002528 }
Chris Allegretta327abda2003-01-17 05:04:17 +00002529#endif
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002530 break;
2531 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002532#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002533 if (history_list != NULL) {
2534 /* Get the newer search from the history list and
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002535 * save it in answer. If there is no newer search,
2536 * don't do anything. */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002537 if ((history =
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002538 get_history_newer(&history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002539 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002540 statusbar_x = strlen(answer);
Chris Allegrettac30fc242003-08-11 00:32:45 +00002541 }
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002542
2543 /* If, after scrolling down, we're at the bottom of
2544 * the history list, answer is blank, and
2545 * magichistory is set, save magichistory in
2546 * answer. */
2547 if (history_list->next == NULL &&
2548 answer[0] == '\0' && magichistory != NULL) {
2549 answer = mallocstrcpy(answer, magichistory);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002550 statusbar_x = strlen(answer);
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002551 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002552 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002553#endif
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002554 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002555 }
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002556
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002557 /* If we have a shortcut with an associated function, break out
2558 * if we're finished after running or trying to run the
2559 * function. */
2560 if (finished)
2561 break;
2562
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002563 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002564 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002565 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002566
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002567#ifndef NANO_SMALL
David Lawrence Ramsey8234f672005-06-02 02:32:39 +00002568 /* Free magichistory if we need to. */
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002569 if (magichistory != NULL)
2570 free(magichistory);
2571#endif
2572
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002573 /* We finished putting in an answer or ran a normal shortcut's
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002574 * associated function, so reset statusbar_x. */
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002575 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002576 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002577 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002578
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002579 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002580}
2581
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002582/* Ask a question on the statusbar. Answer will be stored in answer
2583 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002584 * otherwise, the valid shortcut key caught. curranswer is any editable
2585 * text that we want to put up by default.
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002586 *
David Lawrence Ramsey67e3b932005-05-23 18:49:28 +00002587 * The allow_tabs parameter indicates whether we should allow tabs to be
2588 * interpreted. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002589int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002590#ifndef NANO_SMALL
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002591 filestruct *history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002592#endif
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002593 const char *msg, ...)
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002594{
2595 va_list ap;
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002596 char *foo = charalloc(((COLS - 4) * mb_cur_max()) + 1);
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002597 int retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002598#ifndef DISABLE_TABCOMP
2599 bool list = FALSE;
2600#endif
2601
2602 bottombars(s);
2603
2604 va_start(ap, msg);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002605 vsnprintf(foo, (COLS - 4) * mb_cur_max(), msg, ap);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002606 va_end(ap);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002607 null_at(&foo, actual_x(foo, COLS - 4));
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002608
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002609 retval = nanogetstr(allow_tabs, foo, curranswer,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002610#ifndef NANO_SMALL
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002611 history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002612#endif
2613 s
2614#ifndef DISABLE_TABCOMP
2615 , &list
2616#endif
2617 );
2618 free(foo);
2619 resetstatuspos = FALSE;
2620
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002621 switch (retval) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002622 case NANO_CANCEL_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002623 retval = -1;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002624 resetstatuspos = TRUE;
2625 break;
2626 case NANO_ENTER_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002627 retval = (answer[0] == '\0') ? -2 : 0;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002628 resetstatuspos = TRUE;
2629 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002630 }
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002631
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002632 blank_statusbar();
2633
2634#ifdef DEBUG
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002635 fprintf(stderr, "answer = \"%s\"\n", answer);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002636#endif
2637
2638#ifndef DISABLE_TABCOMP
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002639 /* If we've done tab completion, there might be a list of
2640 * filename matches on the edit window at this point. Make sure
2641 * that they're cleared off. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002642 if (list)
2643 edit_refresh();
2644#endif
2645
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002646 return retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002647}
2648
2649void statusq_abort(void)
2650{
2651 resetstatuspos = TRUE;
2652}
2653
Chris Allegrettaf717f982003-02-13 22:25:01 +00002654void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002655{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002656 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002657 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002658 size_t verlen = strlenpt(VERMSG) + 1;
2659 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002660 const char *prefix;
2661 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2662 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002663 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002664 const char *state;
2665 /* "Modified", "View", or spaces the length of "Modified".
2666 * Tells the state of this buffer. */
2667 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002668 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002669 char *exppath = NULL;
2670 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002671 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002672 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002673 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002674 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002675
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002676 assert(path != NULL || filename != NULL);
2677 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002678
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002679 wattron(topwin, A_REVERSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002680 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002681
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002682 if (COLS <= 5 || COLS - 5 < verlen)
2683 space = 0;
2684 else {
2685 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002686 /* Reserve 2/3 of the screen plus one column for after the
2687 * version message. */
2688 if (space < COLS - (COLS / 3) + 1)
2689 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002690 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002691
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002692 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002693 /* The version message should only take up 1/3 of the screen
2694 * minus one column. */
2695 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002696 waddstr(topwin, " ");
2697 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002698
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002699 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002700 state = _("Modified");
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002701 else if (ISSET(VIEW_MODE))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002702 state = _("View");
2703 else {
2704 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002705 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002706 state = &hblank[COLS - statelen];
2707 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002708 statelen = strnlenpt(state, COLS);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002709
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002710 /* We need a space before state. */
2711 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2712 statelen++;
2713
2714 assert(space >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002715
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002716 if (space == 0 || statelen >= space)
2717 goto the_end;
2718
2719#ifndef DISABLE_BROWSER
2720 if (path != NULL)
2721 prefix = _("DIR:");
2722 else
2723#endif
2724 if (filename[0] == '\0') {
2725 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002726 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002727 } else
2728 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002729
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002730 assert(statelen < space);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002731
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002732 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002733
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002734 /* If newfie is FALSE, we need a space after prefix. */
2735 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002736 prefixlen++;
2737
2738 if (path == NULL)
2739 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002740 if (space >= prefixlen + statelen)
2741 space -= prefixlen + statelen;
2742 else
2743 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002744 /* space is now the room we have for the file name. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002745
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002746 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002747 size_t lenpt = strlenpt(path), start_col;
2748
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002749 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002750
2751 if (dots) {
2752 start_col = lenpt - space + 3;
2753 space -= 3;
2754 } else
2755 start_col = 0;
2756
2757 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002758 }
2759
2760 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002761 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2762 /* The length of the expanded filename. */
2763
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002764 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002765 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002766 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002767 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002768 assert(strlenpt(prefix) + 1 == prefixlen);
2769
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002770 waddch(topwin, ' ');
2771 waddstr(topwin, exppath);
2772 }
2773 } else {
2774 /* We will say something like "File: ...ename". */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002775 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002776 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002777 goto the_end;
2778 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002779 waddnstr(topwin, "...", space + 3);
2780 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002781 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002782 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002783 }
2784
2785 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002786 free(exppath);
2787
2788 if (COLS <= 1 || statelen >= COLS - 1)
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002789 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002790 else {
2791 assert(COLS - statelen - 2 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002792
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002793 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002794 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
2795 actual_x(state, statelen));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002796 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002797
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002798 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002799
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002800 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002801 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002802 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002803}
2804
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002805/* If modified is not already set, set it and update titlebar. */
2806void set_modified(void)
2807{
2808 if (!ISSET(MODIFIED)) {
2809 SET(MODIFIED);
2810 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002811 }
2812}
2813
2814void statusbar(const char *msg, ...)
2815{
2816 va_list ap;
2817
2818 va_start(ap, msg);
2819
2820 /* Curses mode is turned off. If we use wmove() now, it will muck
2821 * up the terminal settings. So we just use vfprintf(). */
2822 if (curses_ended) {
2823 vfprintf(stderr, msg, ap);
2824 va_end(ap);
2825 return;
2826 }
2827
2828 /* Blank out the line. */
2829 blank_statusbar();
2830
2831 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002832 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002833 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002834#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002835 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002836
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002837 UNSET(WHITESPACE_DISPLAY);
2838#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002839 bar = charalloc(mb_cur_max() * (COLS - 3));
2840 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002841 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002842 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002843#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2844 if (old_whitespace)
2845 SET(WHITESPACE_DISPLAY);
2846#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002847 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002848 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002849 start_x = (COLS - foo_len - 4) / 2;
2850
2851 wmove(bottomwin, 0, start_x);
2852 wattron(bottomwin, A_REVERSE);
2853
2854 waddstr(bottomwin, "[ ");
2855 waddstr(bottomwin, foo);
2856 free(foo);
2857 waddstr(bottomwin, " ]");
2858 wattroff(bottomwin, A_REVERSE);
2859 wnoutrefresh(bottomwin);
2860 reset_cursor();
2861 wrefresh(edit);
2862 /* Leave the cursor at its position in the edit window, not
2863 * in the statusbar. */
2864 }
2865
2866 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002867 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002868}
2869
Chris Allegretta6232d662002-05-12 19:52:15 +00002870void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002871{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002872 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002873
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002874 if (ISSET(NO_HELP))
2875 return;
2876
Chris Allegretta6232d662002-05-12 19:52:15 +00002877 if (s == main_list) {
2878 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002879
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002880 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002881 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002882 slen = length_of_list(s);
2883
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002884 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002885 if (slen > MAIN_VISIBLE)
2886 slen = MAIN_VISIBLE;
2887 }
2888
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002889 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002890 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002891 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002892
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002893 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002894
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002895 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002896 const char *keystr;
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002897 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002898
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002899 /* Yucky sentinel values that we can't handle a better way. */
2900 if (s->ctrlval == NANO_CONTROL_SPACE)
2901 strcpy(foo, "^ ");
2902 else if (s->ctrlval == NANO_CONTROL_8)
2903 strcpy(foo, "^?");
2904 /* Normal values. Assume that the shortcut has an equivalent
2905 * control key, meta key sequence, or both. */
2906 else if (s->ctrlval != NANO_NO_KEY)
2907 sprintf(foo, "^%c", s->ctrlval + 64);
2908 else if (s->metaval != NANO_NO_KEY)
2909 sprintf(foo, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00002910
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002911 keystr = foo;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002912
2913 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002914 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002915 }
2916
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002917 wnoutrefresh(bottomwin);
2918 reset_cursor();
2919 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002920}
2921
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002922/* Write a shortcut key to the help area at the bottom of the window.
2923 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2924 * to write at most len characters, even if len is very small and
2925 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2926 * the whole string! We do not bother padding the entry with blanks. */
2927void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002928{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002929 size_t keystroke_len = strlenpt(keystroke) + 1;
2930
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002931 assert(keystroke != NULL && desc != NULL);
2932
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002933 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002934 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002935 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002936
2937 if (len > keystroke_len)
2938 len -= keystroke_len;
2939 else
2940 len = 0;
2941
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002942 if (len > 0) {
2943 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002944 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002945 }
2946}
2947
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002948/* And so start the display update routines. */
2949
2950#ifndef NDEBUG
2951int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002952{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002953 int check_line = 0;
2954 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002955
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002956 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
2957 check_line++;
2958 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002959}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002960#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00002961
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002962/* nano scrolls horizontally within a line in chunks. This function
2963 * returns the column number of the first character displayed in the
2964 * window when the cursor is at the given column. Note that
2965 * 0 <= column - get_page_start(column) < COLS. */
2966size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002967{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002968 assert(COLS > 0);
2969 if (column == 0 || column < COLS - 1)
2970 return 0;
2971 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002972 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002973 else if (COLS > 2)
2974 return column - (COLS - 2);
2975 else
2976 return column - (COLS - 1);
2977 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002978}
2979
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002980/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002981 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002982void reset_cursor(void)
2983{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002984 /* If we haven't opened any files yet, put the cursor in the top
2985 * left corner of the edit window and get out. */
2986 if (edittop == NULL || current == NULL) {
2987 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002988 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002989 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002990
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002991 current_y = current->lineno - edittop->lineno;
2992 if (current_y < editwinrows) {
2993 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002994 wmove(edit, current_y, x - get_page_start(x));
2995 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002996}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002997
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002998/* edit_add() takes care of the job of actually painting a line into the
2999 * edit window. fileptr is the line to be painted, at row yval of the
3000 * window. converted is the actual string to be written to the window,
3001 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003002 * characters. start is the column number of the first character of
3003 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003004 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003005void edit_add(const filestruct *fileptr, const char *converted, int
3006 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003007{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003008#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003009 size_t startpos = actual_x(fileptr->data, start);
3010 /* The position in fileptr->data of the leftmost character
3011 * that displays at least partially on the window. */
3012 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3013 /* The position in fileptr->data of the first character that is
3014 * completely off the window to the right.
3015 *
3016 * Note that endpos might be beyond the null terminator of the
3017 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003018#endif
3019
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003020 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003021 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003022
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003023 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003024 * just the text that needs it). */
3025 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003026
Chris Allegretta7dd77682001-12-08 19:52:28 +00003027#ifdef ENABLE_COLOR
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003028 if (colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003029 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003030
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003031 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3032 int x_start;
3033 /* Starting column for mvwaddnstr. Zero-based. */
3034 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003035 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003036 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003037 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003038 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003039 regmatch_t startmatch; /* match position for start_regexp */
3040 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003041
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003042 if (tmpcolor->bright)
3043 wattron(edit, A_BOLD);
3044 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003045 /* Two notes about regexec(). Return value 0 means there is
3046 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003047 * after the match. */
3048
3049 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003050 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003051 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003052
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003053 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003054 * last match. Even though two matches may overlap, we
3055 * want to ignore them, so that we can highlight
3056 * C-strings correctly. */
3057 while (k < endpos) {
3058 /* Note the fifth parameter to regexec(). It says
3059 * not to match the beginning-of-line character
3060 * unless k is 0. If regexec() returns REG_NOMATCH,
3061 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003062 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003063 &startmatch, (k == 0) ? 0 :
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003064 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003065 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003066 /* Translate the match to the beginning of the
3067 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003068 startmatch.rm_so += k;
3069 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003070 if (startmatch.rm_so == startmatch.rm_eo) {
3071 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003072 statusbar(
3073 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003074 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003075 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003076 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003077 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003078 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003079 x_start = strnlenpt(fileptr->data,
3080 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003081
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003082 index = actual_x(converted, x_start);
3083
3084 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003085 strnlenpt(fileptr->data,
3086 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003087
3088 assert(0 <= x_start && 0 <= paintlen);
3089
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003090 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003091 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003092 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003093 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003094 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003095 } else {
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003096 /* This is a multi-line regexp. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003097 * First, we have to see if the beginning of the line is
3098 * colored by a start on an earlier line, and an end on
3099 * this line or later.
3100 *
3101 * We find the first line before fileptr matching the
3102 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003103 * end, then go to step two. Otherwise, find the next
3104 * line after start_line matching the end. If that line
3105 * is not before fileptr, then paint the beginning of
3106 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003107 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003108 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003109 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003110 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003111 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003112
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003113 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003114 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003115 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003116 /* If there is an end on this line, there is no need
3117 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003118 if (regexec(tmpcolor->end, start_line->data, 0,
3119 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003120 goto step_two;
3121 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003122 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003123 /* No start found, so skip to the next step. */
3124 if (start_line == NULL)
3125 goto step_two;
3126 /* Now start_line is the first line before fileptr
3127 * containing a start match. Is there a start on this
3128 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003129 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003130 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003131 start_col += startmatch.rm_so;
3132 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003133 if (regexec(tmpcolor->end, start_line->data +
3134 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003135 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003136 REG_NOTBOL) == REG_NOMATCH)
3137 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003138 break;
3139 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003140 if (regexec(&tmpcolor->start, start_line->data +
3141 start_col, 1, &startmatch,
3142 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003143 /* No later start on this line. */
3144 goto step_two;
3145 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003146 /* Indeed, there is a start not followed on this line by
3147 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003148
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003149 /* We have already checked that there is no end before
3150 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003151 * the start at all? We don't paint unterminated
3152 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003153 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003154 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003155 regexec(tmpcolor->end, end_line->data, 1,
3156 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003157 end_line = end_line->next;
3158
3159 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003160 if (end_line == NULL || (end_line == fileptr &&
3161 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003162 goto step_two;
3163
3164 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003165 if (end_line != fileptr)
3166 /* If the start of fileptr is on a different line
3167 * from the end, paintlen is -1, meaning that
3168 * everything on the line gets painted. */
3169 paintlen = -1;
3170 else
3171 /* Otherwise, paintlen is the expanded location of
3172 * the end of the match minus the expanded location
3173 * of the beginning of the page. */
3174 paintlen = actual_x(converted,
3175 strnlenpt(fileptr->data, endmatch.rm_eo) -
3176 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003177
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003178 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003179
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003180 step_two:
3181 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003182 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003183
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003184 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003185 if (regexec(&tmpcolor->start,
3186 fileptr->data + start_col, 1, &startmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003187 (start_col == 0) ? 0 :
3188 REG_NOTBOL) == REG_NOMATCH ||
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003189 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003190 /* No more starts on this line. */
3191 break;
3192 /* Translate the match to be relative to the
3193 * beginning of the line. */
3194 startmatch.rm_so += start_col;
3195 startmatch.rm_eo += start_col;
3196
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003197 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003198 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003199 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003200 x_start = strnlenpt(fileptr->data,
3201 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003202
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003203 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003204
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003205 if (regexec(tmpcolor->end,
3206 fileptr->data + startmatch.rm_eo, 1, &endmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003207 (startmatch.rm_eo == 0) ? 0 :
3208 REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003209 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003210 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003211 endmatch.rm_so += startmatch.rm_eo;
3212 endmatch.rm_eo += startmatch.rm_eo;
3213 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003214 * appear on this page, and is the match more
3215 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003216 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003217 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003218 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003219 strnlenpt(fileptr->data,
3220 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003221
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003222 assert(0 <= x_start && x_start < COLS);
3223
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003224 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003225 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003226 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003227 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003228 /* There is no end on this line. But we haven't
3229 * yet looked for one on later lines. */
3230 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003231
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003232 while (end_line != NULL &&
3233 regexec(tmpcolor->end, end_line->data,
3234 0, NULL, 0) == REG_NOMATCH)
3235 end_line = end_line->next;
3236
3237 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003238 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003239
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003240 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003241 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003242 /* We painted to the end of the line, so
3243 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003244 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003245 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003246 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003247 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003248 }
3249 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003250
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003251 wattroff(edit, A_BOLD);
3252 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003253 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003254 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003255#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003256
Chris Allegretta7dd77682001-12-08 19:52:28 +00003257#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003258 if (ISSET(MARK_ISSET)
3259 && (fileptr->lineno <= mark_beginbuf->lineno
3260 || fileptr->lineno <= current->lineno)
3261 && (fileptr->lineno >= mark_beginbuf->lineno
3262 || fileptr->lineno >= current->lineno)) {
3263 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003264
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003265 const filestruct *top;
3266 /* Either current or mark_beginbuf, whichever is first. */
3267 size_t top_x;
3268 /* current_x or mark_beginx, corresponding to top. */
3269 const filestruct *bot;
3270 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003271 int x_start;
3272 /* Starting column for mvwaddnstr. Zero-based. */
3273 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003274 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003275 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003276 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003277 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003278
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003279 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003280
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003281 if (top->lineno < fileptr->lineno || top_x < startpos)
3282 top_x = startpos;
3283 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3284 bot_x = endpos;
3285
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003286 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003287 if (top_x < endpos && bot_x > startpos) {
3288 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003289
3290 /* x_start is the expanded location of the beginning of the
3291 * mark minus the beginning of the page. */
3292 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003293
3294 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003295 /* If the end of the mark is off the page, paintlen is
3296 * -1, meaning that everything on the line gets
3297 * painted. */
3298 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003299 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003300 /* Otherwise, paintlen is the expanded location of the
3301 * end of the mark minus the expanded location of the
3302 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003303 paintlen = strnlenpt(fileptr->data, bot_x) -
3304 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003305
3306 /* If x_start is before the beginning of the page, shift
3307 * paintlen x_start characters to compensate, and put
3308 * x_start at the beginning of the page. */
3309 if (x_start < 0) {
3310 paintlen += x_start;
3311 x_start = 0;
3312 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003313
3314 assert(x_start >= 0 && x_start <= strlen(converted));
3315
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003316 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003317
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003318 if (paintlen > 0)
3319 paintlen = actual_x(converted + index, paintlen);
3320
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003321 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003322 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003323 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003324 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003325 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003326 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003327#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003328}
3329
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003330/* Just update one line in the edit buffer. This is basically a wrapper
3331 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003332 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003333 * If fileptr != current, then index is considered 0. The line will be
3334 * displayed starting with fileptr->data[index]. Likely args are
3335 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003336void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003337{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003338 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003339 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003340 char *converted;
3341 /* fileptr->data converted to have tabs and control characters
3342 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003343 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003344
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003345 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003346
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003347 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003348
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003349 /* We assume the line numbers are valid. Is that really true? */
3350 assert(line < 0 || line == check_linenumbers(fileptr));
3351
3352 if (line < 0 || line >= editwinrows)
3353 return;
3354
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003355 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003356 mvwaddstr(edit, line, 0, hblank);
3357
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003358 /* Next, convert variables that index the line to their equivalent
3359 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003360 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003361 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003362
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003363 /* Expand the line, replacing tabs with spaces, and control
3364 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003365 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003366
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003367 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003368 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003369 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003370
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003371 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003372 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003373 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003374 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003375}
3376
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003377/* Return a nonzero value if we need an update after moving
3378 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003379 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003380int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003381{
3382 return
3383#ifndef NANO_SMALL
3384 ISSET(MARK_ISSET) ||
3385#endif
3386 get_page_start(old_pww) != get_page_start(placewewant);
3387}
3388
3389/* Return a nonzero value if we need an update after moving vertically.
3390 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003391 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003392int need_vertical_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/* Scroll the edit window in the given direction and the given number
3402 * of lines, and draw new lines on the blank lines left after the
3403 * scrolling. direction is the direction to scroll, either UP or DOWN,
3404 * and nlines is the number of lines to scroll. Don't redraw the old
3405 * topmost or bottommost line (where we assume current is) before
3406 * scrolling or draw the new topmost or bottommost line after scrolling
3407 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003408 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003409void edit_scroll(updown direction, int nlines)
3410{
3411 filestruct *foo;
3412 int i, scroll_rows = 0;
3413
3414 /* Scrolling less than one line or more than editwinrows lines is
3415 * redundant, so don't allow it. */
3416 if (nlines < 1 || nlines > editwinrows)
3417 return;
3418
3419 /* Move the top line of the edit window up or down (depending on the
3420 * value of direction) nlines lines. If there are fewer lines of
3421 * text than that left, move it to the top or bottom line of the
3422 * file (depending on the value of direction). Keep track of
3423 * how many lines we moved in scroll_rows. */
3424 for (i = nlines; i > 0; i--) {
3425 if (direction == UP) {
3426 if (edittop->prev == NULL)
3427 break;
3428 edittop = edittop->prev;
3429 scroll_rows--;
3430 } else {
3431 if (edittop->next == NULL)
3432 break;
3433 edittop = edittop->next;
3434 scroll_rows++;
3435 }
3436 }
3437
3438 /* Scroll the text on the screen up or down scroll_rows lines,
3439 * depending on the value of direction. */
3440 scrollok(edit, TRUE);
3441 wscrl(edit, scroll_rows);
3442 scrollok(edit, FALSE);
3443
3444 foo = edittop;
3445 if (direction != UP) {
3446 int slines = editwinrows - nlines;
3447 for (; slines > 0 && foo != NULL; slines--)
3448 foo = foo->next;
3449 }
3450
3451 /* And draw new lines on the blank top or bottom lines of the edit
3452 * window, depending on the value of direction. Don't draw the new
3453 * topmost or new bottommost line. */
3454 while (scroll_rows != 0 && foo != NULL) {
3455 if (foo->next != NULL)
3456 update_line(foo, 0);
3457 if (direction == UP)
3458 scroll_rows++;
3459 else
3460 scroll_rows--;
3461 foo = foo->next;
3462 }
3463}
3464
3465/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003466 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003467void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003468{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003469 int do_refresh = need_vertical_update(0) ||
3470 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003471 const filestruct *foo;
3472
3473 /* If either old_current or current is offscreen, refresh the screen
3474 * and get out. */
3475 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3476 edittop->lineno + editwinrows || current->lineno <
3477 edittop->lineno || current->lineno >= edittop->lineno +
3478 editwinrows) {
3479 edit_refresh();
3480 return;
3481 }
3482
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003483 /* Update old_current and current if we're not on the first page
3484 * and/or we're not on the same page as before. If the mark is on,
3485 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003486 foo = old_current;
3487 while (foo != current) {
3488 if (do_refresh)
3489 update_line(foo, 0);
3490#ifndef NANO_SMALL
3491 if (!ISSET(MARK_ISSET))
3492#endif
3493 break;
3494 if (foo->lineno > current->lineno)
3495 foo = foo->prev;
3496 else
3497 foo = foo->next;
3498 }
3499 if (do_refresh)
3500 update_line(current, current_x);
3501}
3502
Chris Allegretta6df90f52002-07-19 01:08:59 +00003503/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003504void edit_refresh(void)
3505{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003506 if (current->lineno < edittop->lineno ||
3507 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003508 /* Note that edit_update() changes edittop so that it's in range
3509 * of current. Thus, when it then calls edit_refresh(), there
3510 * is no danger of getting an infinite loop. */
3511 edit_update(
3512#ifndef NANO_SMALL
3513 ISSET(SMOOTHSCROLL) ? NONE :
3514#endif
3515 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003516 else {
3517 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003518 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003519
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003520#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003521 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003522#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003523
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003524 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003525 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003526 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003527 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003528 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003529 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003530 }
3531 while (nlines < editwinrows) {
3532 mvwaddstr(edit, nlines, 0, hblank);
3533 nlines++;
3534 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003535 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003536 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003537 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003538}
3539
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003540/* A nice generic routine to update the edit buffer. We keep current in
3541 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003542void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003543{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003544 filestruct *foo = current;
3545
Chris Allegretta6df90f52002-07-19 01:08:59 +00003546 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003547 /* If location is CENTER, we move edittop up (editwinrows / 2)
3548 * lines. This puts current at the center of the screen. If
3549 * location is NONE, we move edittop up current_y lines if
3550 * current_y is in range of the screen, 0 lines if current_y is
3551 * less than 0, or (editwinrows - 1) lines if current_y is
3552 * greater than (editwinrows - 1). This puts current at the
3553 * same place on the screen as before, or at the top or bottom
3554 * of the screen if edittop is beyond either. */
3555 int goal;
3556
3557 if (location == CENTER)
3558 goal = editwinrows / 2;
3559 else {
3560 goal = current_y;
3561
3562 /* Limit goal to (editwinrows - 1) lines maximum. */
3563 if (goal > editwinrows - 1)
3564 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003565 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003566
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003567 for (; goal > 0 && foo->prev != NULL; goal--)
3568 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003569 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003570
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003571 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003572 edit_refresh();
3573}
3574
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003575/* Ask a simple yes/no question, specified in msg, on the statusbar.
3576 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3577 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003578int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003579{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003580 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003581 const char *yesstr; /* String of yes characters accepted. */
3582 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003583 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003584
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003585 /* yesstr, nostr, and allstr are strings of any length. Each string
David Lawrence Ramseydcb4e3a2005-04-08 20:27:02 +00003586 * consists of all single-byte characters accepted as valid
3587 * characters for that value. The first value will be the one
3588 * displayed in the shortcuts. Translators: if possible, specify
3589 * both the shortcuts for your language and English. For example,
3590 * in French: "OoYy" for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003591 yesstr = _("Yy");
3592 nostr = _("Nn");
3593 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003594
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003595 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003596 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003597
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003598 if (COLS < 32)
3599 width = COLS / 2;
3600
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003601 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003602 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003603
Chris Allegretta6232d662002-05-12 19:52:15 +00003604 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003605 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003606 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003607
3608 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003609 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003610 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003611 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003612 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003613
Chris Allegrettadb28e962003-01-28 01:23:40 +00003614 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003615 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003616 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003617
Chris Allegrettadb28e962003-01-28 01:23:40 +00003618 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003619 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003620 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003621
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003622 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003623
3624 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003625 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003626
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003627 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003628
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003629 wrefresh(bottomwin);
3630
Chris Allegrettadb28e962003-01-28 01:23:40 +00003631 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003632 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003633 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003634#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003635 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003636#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003637
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003638 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003639
3640 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003641 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003642#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003643 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003644 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003645
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003646 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003647 wenclose(bottomwin, mouse_y, mouse_x) &&
3648 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003649 int x = mouse_x / width;
3650 /* Did we click in the first column of shortcuts, or
3651 * the second? */
3652 int y = mouse_y - editwinrows - 3;
3653 /* Did we click in the first row of shortcuts? */
3654
3655 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3656
3657 /* x = 0 means they clicked Yes or No.
3658 * y = 0 means Yes or All. */
3659 ok = -2 * x * y + x - y + 1;
3660
3661 if (ok == 2 && !all)
3662 ok = -2;
3663 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003664 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003665#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003666 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003667 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003668 else if (strchr(yesstr, kbinput) != NULL)
3669 ok = 1;
3670 else if (strchr(nostr, kbinput) != NULL)
3671 ok = 0;
3672 else if (all && strchr(allstr, kbinput) != NULL)
3673 ok = 2;
3674 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003675
Chris Allegrettadb28e962003-01-28 01:23:40 +00003676 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003677}
3678
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003679void total_update(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003680{
David Lawrence Ramsey0bfec6e2005-04-25 20:08:29 +00003681 clearok(edit, TRUE);
3682 wrefresh(edit);
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003683}
3684
3685void total_refresh(void)
3686{
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003687 total_update();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003688 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003689 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003690 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003691}
3692
3693void display_main_list(void)
3694{
3695 bottombars(main_list);
3696}
3697
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003698/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3699 * display the cursor position. Otherwise, we display it only if the
3700 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003701 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003702 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3703 * old_i and old_totsize. That way, we leave the current statusbar
3704 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003705void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003706{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003707 char c;
3708 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003709 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003710 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003711
Chris Allegrettad26ab912003-01-28 01:16:47 +00003712 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003713
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003714 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003715 old_totsize = totsize;
3716
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003717 c = current->data[current_x];
3718 f = current->next;
3719 current->data[current_x] = '\0';
3720 current->next = NULL;
3721 get_totals(fileage, current, NULL, &i);
3722 current->data[current_x] = c;
3723 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003724
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003725 /* Check whether totsize is correct. Else there is a bug
3726 * somewhere. */
3727 assert(current != filebot || i == totsize);
3728
Chris Allegrettad26ab912003-01-28 01:16:47 +00003729 if (constant && ISSET(DISABLE_CURPOS)) {
3730 UNSET(DISABLE_CURPOS);
3731 old_i = i;
3732 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003733 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003734 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003735
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003736 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003737 * unconditionally; otherwise, only display the position when the
3738 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003739 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003740 size_t xpt = xplustabs() + 1;
3741 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003742 int linepct = 100 * current->lineno / totlines;
3743 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003744 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003745
3746 statusbar(
3747 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3748 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003749 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003750 (unsigned long)i, (unsigned long)totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003751 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003752 }
3753
3754 old_i = i;
3755 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003756}
3757
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003758void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003759{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003760 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003761}
3762
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003763#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003764/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003765size_t help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003766{
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003767 int help_cols = (COLS > 24) ? COLS - 8 : 24;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003768
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003769 /* Try to break the line at (COLS - 8) columns if we have more than
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003770 * 24 columns, and at 24 columns otherwise. */
David Lawrence Ramsey40e211b2005-03-19 21:15:30 +00003771 size_t retval = break_line(ptr, help_cols, TRUE);
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003772 size_t retval_save = retval;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003773
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003774 /* Get the length of the entire line up to a null or a newline. */
3775 while (*(ptr + retval) != '\0' && *(ptr + retval) != '\n')
3776 retval += move_mbright(ptr + retval, 0);
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003777
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003778 /* If the entire line doesn't go more than 8 columns beyond where we
3779 * tried to break it, we should display it as-is. Otherwise, we
3780 * should display it only up to the break. */
3781 if (strnlenpt(ptr, retval) > help_cols + 8)
3782 retval = retval_save;
3783
3784 return retval;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003785}
3786
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003787/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003788void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003789{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003790 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003791 /* The line number in help_text of the first displayed help
3792 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003793 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003794 /* no_more means the end of the help text is shown, so don't go
3795 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003796 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003797 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003798
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003799 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003800#ifndef DISABLE_MOUSE
3801 const shortcut *oldshortcut = currshortcut;
3802 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003803 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003804#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003805
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003806 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003807 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003808 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003809 blank_statusbar();
3810
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003811 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003812 help_init();
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003813
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003814 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003815
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003816#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003817 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003818 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003819 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003820#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003821
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003822 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003823 /* Make sure that the help screen's shortcut list will actually
3824 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003825 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003826 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003827 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003828
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003829 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003830
3831 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003832 int i;
3833 int old_line = line;
3834 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003835 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003836
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003837 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003838#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003839 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003840 {
3841 int mouse_x, mouse_y;
3842 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3843 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003844 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003845#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003846 case NANO_PREVPAGE_KEY:
3847 case NANO_PREVPAGE_FKEY:
3848 if (line > 0) {
3849 line -= editwinrows - 2;
3850 if (line < 0)
3851 line = 0;
3852 }
3853 break;
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003854 case NANO_NEXTPAGE_KEY:
3855 case NANO_NEXTPAGE_FKEY:
3856 if (!no_more)
3857 line += editwinrows - 2;
3858 break;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003859 case NANO_PREVLINE_KEY:
3860 if (line > 0)
3861 line--;
3862 break;
3863 case NANO_NEXTLINE_KEY:
3864 if (!no_more)
3865 line++;
3866 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003867 }
3868
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003869 if (kbinput == NANO_REFRESH_KEY)
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003870 total_update();
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003871 else {
3872 if (line == old_line && kbinput != ERR)
3873 goto skip_redisplay;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003874
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003875 blank_edit();
3876 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003877
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003878 /* Calculate where in the text we should be, based on the
3879 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003880 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003881 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003882 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003883 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003884 }
3885
Chris Allegretta4640fe32003-02-10 03:10:03 +00003886 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003887 size_t j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003888
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003889 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003890 ptr += j;
3891 if (*ptr == '\n')
3892 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003893 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003894 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003895
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003896 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003897 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003898 } while (kbinput != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003899
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003900#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003901 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003902#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003903
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003904 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003905 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003906 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003907 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003908 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003909 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003910 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003911
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003912 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003913 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003914
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003915 /* The help_init() at the beginning allocated help_text. Since
3916 * help_text has now been written to the screen, we don't need it
3917 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003918 free(help_text);
3919 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003920}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003921#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003922
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003923/* Highlight the current word being replaced or spell checked. We
3924 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003925void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003926{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003927 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003928 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003929
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003930 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003931 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003932 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003933
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003934 assert(y > 0);
3935
3936 if (word_len > y)
3937 y--;
3938
Chris Allegrettafb62f732000-12-05 11:36:41 +00003939 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003940
Chris Allegrettafb62f732000-12-05 11:36:41 +00003941 if (highlight_flag)
3942 wattron(edit, A_REVERSE);
3943
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003944#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003945 /* This is so we can show zero-length regexes. */
3946 if (word_len == 0)
3947 waddstr(edit, " ");
3948 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003949#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003950 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003951
3952 if (word_len > y)
3953 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003954
3955 if (highlight_flag)
3956 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003957}
3958
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003959#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003960/* Dump the passed-in file structure to stderr. */
3961void dump_buffer(const filestruct *inptr)
3962{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003963 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003964 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003965 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003966 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003967 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003968 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003969
3970 while (inptr != NULL) {
3971 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
3972 inptr = inptr->next;
3973 }
3974}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003975
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003976/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00003977void dump_buffer_reverse(void)
3978{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003979 const filestruct *fileptr = filebot;
3980
3981 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00003982 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003983 fileptr = fileptr->prev;
3984 }
3985}
3986#endif /* DEBUG */
3987
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003988#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003989#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003990#define XLCREDIT_LEN 8
3991
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00003992/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003993void do_credits(void)
3994{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003995 int crpos = 0, xlpos = 0;
3996 const char *credits[CREDIT_LEN] = {
3997 NULL, /* "The nano text editor" */
3998 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003999 VERSION,
4000 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004001 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004002 "Chris Allegretta",
4003 "Jordi Mallach",
4004 "Adam Rogoyski",
4005 "Rob Siemborski",
4006 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004007 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004008 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004009 "Ken Tyler",
4010 "Sven Guckes",
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004011 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00004012 "Pauli Virtanen",
4013 "Daniele Medri",
4014 "Clement Laforet",
4015 "Tedi Heriyanto",
4016 "Bill Soudan",
4017 "Christian Weisgerber",
4018 "Erik Andersen",
4019 "Big Gaute",
4020 "Joshua Jensen",
4021 "Ryan Krebs",
4022 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004023 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004024 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004025 "Plattsburgh State University",
4026 "Benet Laboratories",
4027 "Amy Allegretta",
4028 "Linda Young",
4029 "Jeremy Robichaud",
4030 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004031 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004032 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004033 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004034 "Thomas Dickey",
4035 "Pavel Curtis",
4036 "Zeyd Ben-Halim",
4037 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004038 NULL, /* "and anyone else we forgot..." */
4039 NULL, /* "Thank you for using nano!" */
4040 "",
4041 "",
4042 "",
4043 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004044 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004045 "",
4046 "",
4047 "",
4048 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004049 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004050 };
4051
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004052 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004053 N_("The nano text editor"),
4054 N_("version"),
4055 N_("Brought to you by:"),
4056 N_("Special thanks to:"),
4057 N_("The Free Software Foundation"),
4058 N_("For ncurses:"),
4059 N_("and anyone else we forgot..."),
4060 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004061 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004062
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004063 curs_set(0);
4064 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004065 scrollok(edit, TRUE);
4066 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004067 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004068 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004069 blank_statusbar();
4070 blank_bottombars();
4071 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004072 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004073 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004074
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004075 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
4076 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004077 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004078
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004079 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004080 char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004081 size_t start_x;
4082
David Lawrence Ramsey631242d2005-03-15 07:06:54 +00004083 /* Make sure every credit is a valid multibyte string, since
4084 * we can't dynamically set the credits to their multibyte
4085 * equivalents when we need to. Sigh... */
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004086 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004087 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004088
4089 what = mallocstrcpy(NULL, _(xlcredits[xlpos]));
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004090 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004091 } else
4092 what = make_mbstring(credits[crpos]);
4093
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004094 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004095 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
4096 start_x, what);
4097
4098 free(what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004099 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004100
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004101 napms(700);
4102 scroll(edit);
4103 wrefresh(edit);
4104 if (wgetch(edit) != ERR)
4105 break;
4106 napms(700);
4107 scroll(edit);
4108 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004109 }
4110
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004111 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004112 nodelay(edit, FALSE);
4113 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004114 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004115}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004116#endif