blob: 60a60eafcb11e85a64041ead4044f88c59f90a9e [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * winio.c *
4 * *
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00005 * Copyright (C) 1999-2005 Chris Allegretta *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00006 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
Jordi Mallach55381aa2004-11-17 23:17:05 +000022#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000025
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000026#include <stdarg.h>
27#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000028#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000029#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000030#include <ctype.h>
Chris Allegretta6232d662002-05-12 19:52:15 +000031#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000032#include "proto.h"
33#include "nano.h"
34
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +000035static int *key_buffer = NULL;
David Lawrence Ramsey74835712004-12-04 17:41:52 +000036 /* The default keystroke buffer,
37 * containing all the keystrokes we have
38 * at a given point. */
39static size_t key_buffer_len = 0;
40 /* The length of the default keystroke
41 * buffer. */
42static int statusblank = 0; /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000043 * we call statusbar(), before we
44 * actually blank the statusbar. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +000045static size_t statusbar_x = (size_t)-1;
46 /* The cursor position in answer. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000047static bool resetstatuspos = FALSE;
48 /* Should we reset the cursor position
49 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000050
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000051/* Control character compatibility:
52 *
53 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
54 * VT100, and VT220.
55 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
56 * VT220, and VT320.
57 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
58 * VT220, and VT320.
59 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
60 * VT220, and VT320.
61 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
62 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000063 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000064 * ANSI, VT100, and VT220, and which is Backspace under VT320.
65 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000066 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000067 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
68 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000069 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000070 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000071 * on which the VT320 sequences are translated by the keypad to KEY_DC
72 * and [nothing]. We work around this conflict via the REBIND_DELETE
73 * flag: if it's not set, we assume VT320 compatibility, and if it is,
74 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
75 * Hemel for helping work this conflict out.
76 *
77 * Escape sequence compatibility:
78 *
79 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000080 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000081 * console), xterm, rxvt, and Eterm. Among these, there are several
82 * conflicts and omissions, outlined as follows:
83 *
84 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
85 * (Ctrl-I is also Tab on ANSI, which we already support.)
86 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
87 * NumLock off on Linux console; the latter is omitted. (The editing
88 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000089 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000090 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
91 * latter is omitted. (Mouse input will only work properly if the
92 * extended keypad value KEY_MOUSE is generated on mouse events
93 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000094 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000095 * omitted. (The editing keypad is more important to have working
96 * than the function keys, because the functions of the former are not
97 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000098 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000099 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000100 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000101 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000102 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
103 * omitted. (The arrow keys, with or without modifiers, are more
104 * important to have working than the function keys, because the
105 * functions of the former are not arbitrary and the functions of the
106 * latter are.)
107 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
108 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000109 *
110 * Note that Center (5) on the numeric keypad with NumLock off can also
111 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000112
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000113#ifndef NANO_SMALL
114/* Reset all the input routines that rely on character sequences. */
115void reset_kbinput(void)
116{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000117 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000118 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000119 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000120}
121#endif
122
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000123/* Read in a sequence of keystrokes from win and save them in the
124 * default keystroke buffer. This should only be called when the
125 * default keystroke buffer is empty. */
126void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000127{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000128 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000129
130 /* If the keystroke buffer isn't empty, get out. */
131 if (key_buffer != NULL)
132 return;
133
134 /* Read in the first character using blocking input. */
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000135#ifndef NANO_SMALL
136 allow_pending_sigwinch(TRUE);
137#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000138
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000139 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000140
David Lawrence Ramseyc275dc52005-03-08 17:45:36 +0000141 /* If we get ERR when using blocking input, it means that the input
142 * source that we were using is gone, so die gracefully. */
143 if (input == ERR)
144 handle_hupterm(0);
145
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000146#ifndef NANO_SMALL
147 allow_pending_sigwinch(FALSE);
148#endif
149
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000150 /* Increment the length of the keystroke buffer, save the value of
151 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000152 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000153 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000154 key_buffer = (int *)nmalloc(sizeof(int));
155 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000156
157 /* Read in the remaining characters using non-blocking input. */
158 nodelay(win, TRUE);
159
160 while (TRUE) {
161#ifndef NANO_SMALL
162 allow_pending_sigwinch(TRUE);
163#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000164
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000165 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000166
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000167 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000168 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000169 break;
170
171 /* Otherwise, increment the length of the keystroke buffer, save
172 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000173 * if the keystroke is an extended keypad value or FALSE if it
174 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000175 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000176 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
177 sizeof(int));
178 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000179
180#ifndef NANO_SMALL
181 allow_pending_sigwinch(FALSE);
182#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000183 }
184
185 /* Switch back to non-blocking input. */
186 nodelay(win, FALSE);
David Lawrence 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
1890 if (ISSET(CUT_TO_END))
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001891 null_at(&answer, statusbar_x);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001892 else {
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001893 null_at(&answer, 0);
1894 statusbar_x = 0;
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001895 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001896}
1897
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001898#ifndef NANO_SMALL
1899void do_statusbar_next_word(void)
1900{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001901 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001902 int char_mb_len;
1903
1904 assert(answer != NULL);
1905
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001906 char_mb = charalloc(mb_cur_max());
1907
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001908 /* Move forward until we find the character after the last letter of
1909 * the current word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001910 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001911 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1912 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001913
1914 /* If we've found it, stop moving forward through the current
1915 * line. */
1916 if (!is_alnum_mbchar(char_mb))
1917 break;
1918
1919 statusbar_x += char_mb_len;
1920 }
1921
1922 /* Move forward until we find the first letter of the next word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001923 if (answer[statusbar_x] != '\0')
1924 statusbar_x += char_mb_len;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001925
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001926 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001927 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1928 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001929
1930 /* If we've found it, stop moving forward through the current
1931 * line. */
1932 if (is_alnum_mbchar(char_mb))
1933 break;
1934
1935 statusbar_x += char_mb_len;
1936 }
1937
1938 free(char_mb);
1939}
1940
1941void do_statusbar_prev_word(void)
1942{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001943 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001944 int char_mb_len;
1945 bool begin_line = FALSE;
1946
1947 assert(answer != NULL);
1948
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001949 char_mb = charalloc(mb_cur_max());
1950
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001951 /* Move backward until we find the character before the first letter
1952 * of the current word. */
1953 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001954 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1955 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001956
1957 /* If we've found it, stop moving backward through the current
1958 * line. */
1959 if (!is_alnum_mbchar(char_mb))
1960 break;
1961
1962 if (statusbar_x == 0)
1963 begin_line = TRUE;
1964 else
1965 statusbar_x = move_mbleft(answer, statusbar_x);
1966 }
1967
1968 /* Move backward until we find the last letter of the previous
1969 * word. */
1970 if (statusbar_x == 0)
1971 begin_line = TRUE;
1972 else
1973 statusbar_x = move_mbleft(answer, statusbar_x);
1974
1975 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001976 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1977 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001978
1979 /* If we've found it, stop moving backward through the current
1980 * line. */
1981 if (is_alnum_mbchar(char_mb))
1982 break;
1983
1984 if (statusbar_x == 0)
1985 begin_line = TRUE;
1986 else
1987 statusbar_x = move_mbleft(answer, statusbar_x);
1988 }
1989
1990 /* If we've found it, move backward until we find the character
1991 * before the first letter of the previous word. */
1992 if (!begin_line) {
1993 if (statusbar_x == 0)
1994 begin_line = TRUE;
1995 else
1996 statusbar_x = move_mbleft(answer, statusbar_x);
1997
1998 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001999 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
2000 NULL, NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002001
2002 /* If we've found it, stop moving backward through the
2003 * current line. */
2004 if (!is_alnum_mbchar(char_mb))
2005 break;
2006
2007 if (statusbar_x == 0)
2008 begin_line = TRUE;
2009 else
2010 statusbar_x = move_mbleft(answer, statusbar_x);
2011 }
2012
2013 /* If we've found it, move forward to the first letter of the
2014 * previous word. */
2015 if (!begin_line)
2016 statusbar_x += char_mb_len;
2017 }
2018
2019 free(char_mb);
2020}
2021#endif
2022
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002023void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002024{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002025 int *kbinput;
2026 size_t kbinput_len, i;
2027 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002028
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002029 *got_enter = FALSE;
2030
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002031 /* Read in all the verbatim characters. */
2032 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
2033
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002034 /* Display all the verbatim characters at once, not filtering out
2035 * control characters. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002036 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002037
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002038 for (i = 0; i < kbinput_len; i++)
2039 output[i] = (char)kbinput[i];
2040 output[i] = '\0';
2041
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002042 do_statusbar_output(output, kbinput_len, got_enter, TRUE);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002043
2044 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002045}
2046
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002047void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002048 *got_enter, bool allow_cntrls)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002049{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002050 size_t answer_len = strlen(answer), i = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002051 char *char_buf = charalloc(mb_cur_max());
2052 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002053
2054 assert(answer != NULL);
2055
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002056 *got_enter = FALSE;
2057
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002058 while (i < output_len) {
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002059 /* If allow_cntrls is FALSE, filter out nulls and newlines,
2060 * since they're control characters. */
2061 if (allow_cntrls) {
2062 /* Null to newline, if needed. */
2063 if (output[i] == '\0')
2064 output[i] = '\n';
2065 /* Newline to Enter, if needed. */
2066 else if (output[i] == '\n') {
2067 /* Set got_enter to TRUE to indicate that we got the
2068 * Enter key, put back the rest of the characters in
2069 * output so that they can be parsed and output again,
2070 * and get out. */
2071 *got_enter = TRUE;
2072 unparse_kbinput(output + i, output_len - i);
2073 return;
2074 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002075 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002076
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002077 /* Interpret the next multibyte character. If it's an invalid
2078 * multibyte character, interpret it as though it's a byte
2079 * character. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002080 char_buf_len = parse_mbchar(output + i, char_buf, NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002081
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002082 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002083
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002084 /* If allow_cntrls is FALSE, filter out a control character. */
2085 if (!allow_cntrls && is_cntrl_mbchar(output + i - char_buf_len))
2086 continue;
2087
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002088 /* More dangerousness fun =) */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002089 answer = charealloc(answer, answer_len + (char_buf_len * 2));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002090
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002091 assert(statusbar_x <= answer_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002092
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002093 charmove(&answer[statusbar_x + char_buf_len],
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002094 &answer[statusbar_x], answer_len - statusbar_x +
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002095 char_buf_len);
2096 charcpy(&answer[statusbar_x], char_buf, char_buf_len);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002097 answer_len += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002098
2099 do_statusbar_right();
2100 }
2101
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002102 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002103}
2104
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002105/* Return the placewewant associated with current_x, i.e, the zero-based
2106 * column position of the cursor. The value will be no smaller than
2107 * current_x. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002108size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002109{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002110 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002111}
2112
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002113/* actual_x() gives the index in str of the character displayed at
2114 * column xplus. That is, actual_x() is the largest value such that
2115 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2116size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002117{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002118 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002119 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002120 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002121 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002122
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002123 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002124
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002125 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002126 int str_len = parse_mbchar(str, NULL, NULL, &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002127
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002128 if (length > xplus)
2129 break;
2130
2131 i += str_len;
2132 str += str_len;
2133 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002134
Chris Allegretta6df90f52002-07-19 01:08:59 +00002135 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002136}
2137
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002138/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002139 * columns wide are the first size characters of str? */
2140size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002141{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002142 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002143 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002144
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002145 if (size == 0)
2146 return 0;
2147
2148 assert(str != NULL);
2149
2150 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002151 int str_len = parse_mbchar(str, NULL, NULL, &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002152
2153 str += str_len;
2154
2155 if (size <= str_len)
2156 break;
2157
2158 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002159 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002160
Chris Allegretta6df90f52002-07-19 01:08:59 +00002161 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002162}
2163
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002164/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002165size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002166{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002167 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002168}
2169
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002170void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002171{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002172 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002173}
2174
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002175void blank_topbar(void)
2176{
2177 if (!ISSET(MORE_SPACE))
2178 mvwaddstr(topwin, 1, 0, hblank);
2179}
2180
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002181void blank_edit(void)
2182{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002183 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002184 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002185 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002186}
2187
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002188void blank_statusbar(void)
2189{
2190 mvwaddstr(bottomwin, 0, 0, hblank);
2191}
2192
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002193void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002194{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002195 if (statusblank > 1)
2196 statusblank--;
2197 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
2198 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002199 blank_statusbar();
2200 wnoutrefresh(bottomwin);
2201 reset_cursor();
2202 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002203 }
2204}
2205
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002206void blank_bottombars(void)
2207{
2208 if (!ISSET(NO_HELP)) {
2209 mvwaddstr(bottomwin, 1, 0, hblank);
2210 mvwaddstr(bottomwin, 2, 0, hblank);
2211 }
2212}
2213
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002214/* Convert buf into a string that can be displayed on screen. The
2215 * caller wants to display buf starting with column start_col, and
2216 * extending for at most len columns. start_col is zero-based. len is
2217 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002218 * string is dynamically allocated, and should be freed. If dollars is
2219 * TRUE, the caller might put "$" at the beginning or end of the line if
2220 * it's too long. */
2221char *display_string(const char *buf, size_t start_col, size_t len, bool
2222 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002223{
2224 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002225 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002226 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002227 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002228 size_t alloc_len;
2229 /* The length of memory allocated for converted. */
2230 char *converted;
2231 /* The string we return. */
2232 size_t index;
2233 /* Current position in converted. */
2234
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002235 char *buf_mb = charalloc(mb_cur_max());
2236 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002237 bool bad_char;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002238
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002239 /* If dollars is TRUE, make room for the "$" at the end of the
2240 * line. */
2241 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2242 len--;
2243
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002244 if (len == 0)
2245 return mallocstrcpy(NULL, "");
2246
2247 start_index = actual_x(buf, start_col);
2248 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002249
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002250 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002251
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002252 /* Allocate enough space for the entire line. It should contain
2253 * (len + 2) multibyte characters at most. */
2254 alloc_len = mb_cur_max() * (len + 2);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002255
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002256 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002257 index = 0;
2258
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002259 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002260 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002261 /* We don't display all of buf[start_index] since it starts to
2262 * the left of the screen. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002263 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL,
2264 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002265
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002266 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002267 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002268 char *ctrl_buf_mb = charalloc(mb_cur_max());
2269 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002270
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002271 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2272 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002273
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002274 for (i = 0; i < ctrl_buf_mb_len; i++)
2275 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002276
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002277 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002278
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002279 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002280
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002281 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002282 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002283 }
2284#ifdef NANO_WIDE
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002285 else if (mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002286 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002287 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002288
2289 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002290 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002291#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002292 }
2293
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002294 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseybc149412005-02-11 20:23:00 +00002295 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, &bad_char,
2296 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002297
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002298 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002299#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002300 if (ISSET(WHITESPACE_DISPLAY)) {
2301 int i;
2302
2303 for (i = 0; i < whitespace_len[0]; i++)
2304 converted[index++] = whitespace[i];
2305 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002306#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002307 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002308 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002309 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002310 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002311 start_col++;
2312 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002313 /* If buf contains a control character, interpret it. If it
2314 * contains an invalid multibyte control character, interpret
2315 * that character as though it's a normal control character. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002316 } else if (is_cntrl_mbchar(buf_mb)) {
2317 char *ctrl_buf_mb = charalloc(mb_cur_max());
2318 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002319
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002320 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002321 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002322
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002323 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2324 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002325
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002326 for (i = 0; i < ctrl_buf_mb_len; i++)
2327 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002328
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002329 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002330
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002331 free(ctrl_buf_mb);
2332 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002333#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002334 if (ISSET(WHITESPACE_DISPLAY)) {
2335 int i;
2336
2337 for (i = whitespace_len[0]; i < whitespace_len[0] +
2338 whitespace_len[1]; i++)
2339 converted[index++] = whitespace[i];
2340 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002341#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002342 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002343 start_col++;
2344 } else {
2345 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002346
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002347#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002348 /* If buf contains an invalid multibyte non-control
2349 * character, interpret that character as though it's a
2350 * normal non-control character. */
2351 if (!ISSET(NO_UTF8) && bad_char) {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002352 char *bad_buf_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002353 int bad_buf_mb_len;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002354
David Lawrence Ramsey4c6956b2005-01-12 04:32:43 +00002355 bad_buf_mb = make_mbchar((unsigned char)*buf_mb,
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002356 &bad_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002357
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002358 for (i = 0; i < bad_buf_mb_len; i++)
2359 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002360
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002361 start_col += mbwidth(bad_buf_mb);
2362
2363 free(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002364 } else {
2365#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002366 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002367 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002368
2369 start_col += mbwidth(buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002370#ifdef NANO_WIDE
2371 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002372#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002373 }
2374
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002375 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002376 }
2377
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002378 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002379 converted[index] = '\0';
2380
2381 /* Make sure converted takes up no more than len columns. */
2382 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002383 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002384
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002385 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002386}
2387
Chris Allegretta7662c862003-01-13 01:35:15 +00002388/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002389 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002390 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002391 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002392 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002393void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002394{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002395 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002396 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002397
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002398 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002399
Chris Allegrettab3655b42001-10-22 03:15:31 +00002400 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002401 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002402
Chris Allegretta6df90f52002-07-19 01:08:59 +00002403 mvwaddstr(bottomwin, 0, 0, buf);
2404 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002405
2406 if (COLS > 1)
2407 waddch(bottomwin, x_real < wid ? ' ' : '$');
2408 if (COLS > 2) {
2409 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002410 char *expanded = display_string(inputbuf, page_start, wid,
2411 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002412
2413 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002414 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002415
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002416 waddstr(bottomwin, expanded);
2417 free(expanded);
2418 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2419 } else
2420 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002421 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002422}
2423
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002424/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002425 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002426int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002427#ifndef NANO_SMALL
2428 historyheadtype *history_list,
2429#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002430 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002431#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002432 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002433#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002434 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002435{
2436 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002437 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002438 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002439 /* used by input_tab() */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002440 size_t answer_len = strlen(def);
Chris Allegretta598106e2002-01-19 01:59:37 +00002441
Chris Allegretta5beed502003-01-05 20:41:21 +00002442#ifndef NANO_SMALL
2443 /* for history */
2444 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00002445 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00002446 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002447 int last_kbinput = 0;
2448
2449 /* This variable is used in the search history code. use_cb == 0
2450 means that we're using the existing history and ignoring
2451 currentbuf. use_cb == 1 means that the entry in answer should be
2452 moved to currentbuf or restored from currentbuf to answer.
2453 use_cb == 2 means that the entry in currentbuf should be moved to
2454 answer or restored from answer to currentbuf. */
2455 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002456#endif
Chris Allegretta09fc4302003-01-16 22:16:38 +00002457
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002458 /* Only put statusbar_x at the end of the string if it's
2459 * uninitialized, if it would be past the end of the string as it
2460 * is, or if resetstatuspos is TRUE. Otherwise, leave it alone.
2461 * This is so the cursor position stays at the same place if a
2462 * prompt-changing toggle is pressed. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002463 if (statusbar_x == (size_t)-1 || statusbar_x > answer_len ||
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002464 resetstatuspos)
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002465 statusbar_x = answer_len;
Chris Allegretta09fc4302003-01-16 22:16:38 +00002466
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002467 answer = charealloc(answer, answer_len + 1);
2468 if (answer_len > 0)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002469 strcpy(answer, def);
2470 else
2471 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002472
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002473 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002474
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002475 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00002476
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002477 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002478
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002479 /* Refresh the edit window before getting input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002480 wnoutrefresh(edit);
2481 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002482
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002483 /* If we're using restricted mode, we aren't allowed to change the
2484 * name of a file once it has one because that would allow writing
2485 * to files not specified on the command line. In this case,
2486 * disable all keys that would change the text if the filename isn't
2487 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002488 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002489 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002490 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002491
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002492 /* If we have a shortcut with an associated function, break out
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002493 * if we're finished after running or trying to run the
2494 * function. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002495 if (finished)
2496 break;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002497
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002498 assert(statusbar_x <= answer_len && answer_len == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002499
Chris Allegretta04d848e2000-11-05 17:54:41 +00002500 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002501 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00002502
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002503 switch (kbinput) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002504 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002505#ifndef NANO_SMALL
2506 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00002507 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002508 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002509 history_list->current = (historytype *)history_list;
2510 history_list->len = strlen(answer);
2511 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002512
Chris Allegretta7662c862003-01-13 01:35:15 +00002513 if (history_list->len > 0) {
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002514 complete = get_history_completion(history_list,
2515 answer);
Chris Allegretta5beed502003-01-05 20:41:21 +00002516 answer = mallocstrcpy(answer, complete);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002517 answer_len = strlen(answer);
2518 statusbar_x = answer_len;
Chris Allegretta5beed502003-01-05 20:41:21 +00002519 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002520 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002521#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002522 else
2523#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002524#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002525#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002526 if (allow_tabs) {
David Lawrence Ramsey65e6ecb2005-02-08 20:37:53 +00002527 answer = input_tab(answer, &statusbar_x, &tabbed, list);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002528 answer_len = strlen(answer);
Chris Allegretta5beed502003-01-05 20:41:21 +00002529 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002530 break;
David Lawrence Ramsey65e6ecb2005-02-08 20:37:53 +00002531#endif
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002532 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002533#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002534 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002535
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002536 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2537 isn't NULL, and currentbuf is different from answer,
2538 it means that we're scrolling up at the top of the
2539 search history, and we need to save the current
2540 answer in currentbuf; do this and reset use_cb to
2541 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002542 if (currentbuf == NULL || (use_cb == 1 &&
2543 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002544 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002545 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002546 }
2547
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002548 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2549 is different from answer, it means that we're
2550 scrolling up at the bottom of the search history, and
2551 we need to make the string in currentbuf the current
2552 answer; do this, blow away currentbuf since we don't
2553 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002554 if (currentbuf != NULL && use_cb == 2 &&
2555 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002556 answer = mallocstrcpy(answer, currentbuf);
2557 free(currentbuf);
2558 currentbuf = NULL;
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002559 answer_len = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002560 use_cb = 0;
2561
2562 /* else get older search from the history list and save
2563 it in answer; if there is no older search, blank out
2564 answer */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002565 } else if ((history =
2566 get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002567 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002568 answer_len = strlen(history);
Chris Allegretta5beed502003-01-05 20:41:21 +00002569 } else {
2570 answer = mallocstrcpy(answer, "");
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002571 answer_len = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002572 }
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002573 statusbar_x = answer_len;
Chris Allegretta5beed502003-01-05 20:41:21 +00002574 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002575#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002576 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002577 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002578#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002579 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002580
2581 /* get newer search from the history list and save it
2582 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002583 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002584 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002585 answer_len = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002586
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002587 /* if there is no newer search, we're here */
2588
2589 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2590 that we're scrolling down at the bottom of the search
2591 history and we need to make the string in currentbuf
2592 the current answer; do this, blow away currentbuf
2593 since we don't need it anymore, and set use_cb to
2594 1 */
2595 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002596 answer = mallocstrcpy(answer, currentbuf);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002597 answer_len = strlen(answer);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002598 free(currentbuf);
2599 currentbuf = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002600 use_cb = 1;
2601
2602 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2603 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002604 the search history and the current answer (if it's
2605 not blank) needs to be saved in currentbuf; do this,
2606 blank out answer (if necessary), and set use_cb to
2607 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002608 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002609 if (answer[0] != '\0') {
2610 currentbuf = mallocstrcpy(currentbuf, answer);
2611 answer = mallocstrcpy(answer, "");
2612 }
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002613 answer_len = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002614 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002615 }
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002616 statusbar_x = answer_len;
Chris Allegretta5beed502003-01-05 20:41:21 +00002617 }
2618#endif
2619 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002620 }
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002621#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002622 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002623#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002624 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002625 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002626 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002627
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002628 /* We finished putting in an answer or ran a normal shortcut's
2629 * associated function, so reset statusbar_x. */
2630 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
2631 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002632 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002633
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002634 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002635}
2636
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002637/* Ask a question on the statusbar. Answer will be stored in answer
2638 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2639 * otherwise, the valid shortcut key caught. def is any editable text
2640 * we want to put up by default.
2641 *
2642 * New arg tabs tells whether or not to allow tab completion. */
2643int statusq(bool allow_tabs, const shortcut *s, const char *def,
2644#ifndef NANO_SMALL
2645 historyheadtype *which_history,
2646#endif
2647 const char *msg, ...)
2648{
2649 va_list ap;
2650 char *foo = charalloc(COLS - 3);
2651 int ret;
2652#ifndef DISABLE_TABCOMP
2653 bool list = FALSE;
2654#endif
2655
2656 bottombars(s);
2657
2658 va_start(ap, msg);
2659 vsnprintf(foo, COLS - 4, msg, ap);
2660 va_end(ap);
2661 foo[COLS - 4] = '\0';
2662
2663 ret = nanogetstr(allow_tabs, foo, def,
2664#ifndef NANO_SMALL
2665 which_history,
2666#endif
2667 s
2668#ifndef DISABLE_TABCOMP
2669 , &list
2670#endif
2671 );
2672 free(foo);
2673 resetstatuspos = FALSE;
2674
2675 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002676 case NANO_CANCEL_KEY:
2677 ret = -1;
2678 resetstatuspos = TRUE;
2679 break;
2680 case NANO_ENTER_KEY:
2681 ret = (answer[0] == '\0') ? -2 : 0;
2682 resetstatuspos = TRUE;
2683 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002684 }
2685 blank_statusbar();
2686
2687#ifdef DEBUG
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002688 fprintf(stderr, "answer = \"%s\"\n", answer);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002689#endif
2690
2691#ifndef DISABLE_TABCOMP
2692 /* if we've done tab completion, there might be a list of
2693 filename matches on the edit window at this point; make sure
2694 they're cleared off. */
2695 if (list)
2696 edit_refresh();
2697#endif
2698
2699 return ret;
2700}
2701
2702void statusq_abort(void)
2703{
2704 resetstatuspos = TRUE;
2705}
2706
Chris Allegrettaf717f982003-02-13 22:25:01 +00002707void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002708{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002709 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002710 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002711 size_t verlen = strlenpt(VERMSG) + 1;
2712 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002713 const char *prefix;
2714 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2715 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002716 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002717 const char *state;
2718 /* "Modified", "View", or spaces the length of "Modified".
2719 * Tells the state of this buffer. */
2720 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002721 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002722 char *exppath = NULL;
2723 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002724 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002725 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002726 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002727 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002728
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002729 assert(path != NULL || filename != NULL);
2730 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002731
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002732 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002733
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002734 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002735
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002736 if (COLS <= 5 || COLS - 5 < verlen)
2737 space = 0;
2738 else {
2739 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002740 /* Reserve 2/3 of the screen plus one column for after the
2741 * version message. */
2742 if (space < COLS - (COLS / 3) + 1)
2743 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002744 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002745
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002746 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002747 /* The version message should only take up 1/3 of the screen
2748 * minus one column. */
2749 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002750 waddstr(topwin, " ");
2751 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002752
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002753 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002754 state = _("Modified");
2755 else if (path == NULL && ISSET(VIEW_MODE))
2756 state = _("View");
2757 else {
2758 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002759 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002760 state = &hblank[COLS - statelen];
2761 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002762 statelen = strnlenpt(state, COLS);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002763 /* We need a space before state. */
2764 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2765 statelen++;
2766
2767 assert(space >= 0);
2768 if (space == 0 || statelen >= space)
2769 goto the_end;
2770
2771#ifndef DISABLE_BROWSER
2772 if (path != NULL)
2773 prefix = _("DIR:");
2774 else
2775#endif
2776 if (filename[0] == '\0') {
2777 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002778 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002779 } else
2780 prefix = _("File:");
2781 assert(statelen < space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002782 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002783 /* If newfie is FALSE, we need a space after prefix. */
2784 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002785 prefixlen++;
2786
2787 if (path == NULL)
2788 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002789 if (space >= prefixlen + statelen)
2790 space -= prefixlen + statelen;
2791 else
2792 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002793 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002794 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002795 size_t lenpt = strlenpt(path), start_col;
2796
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002797 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002798
2799 if (dots) {
2800 start_col = lenpt - space + 3;
2801 space -= 3;
2802 } else
2803 start_col = 0;
2804
2805 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002806 }
2807
2808 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002809 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2810 /* The length of the expanded filename. */
2811
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002812 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002813 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002814 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002815 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002816 assert(strlenpt(prefix) + 1 == prefixlen);
2817
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002818 waddch(topwin, ' ');
2819 waddstr(topwin, exppath);
2820 }
2821 } else {
2822 /* We will say something like "File: ...ename". */
2823 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002824 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002825 goto the_end;
2826 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002827 waddnstr(topwin, "...", space + 3);
2828 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002829 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002830 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002831 }
2832
2833 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002834 free(exppath);
2835
2836 if (COLS <= 1 || statelen >= COLS - 1)
2837 mvwaddnstr(topwin, 0, 0, state, COLS);
2838 else {
2839 assert(COLS - statelen - 2 >= 0);
2840 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2841 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2842 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002843
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002844 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002845
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002846 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002847 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002848 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002849}
2850
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002851/* If modified is not already set, set it and update titlebar. */
2852void set_modified(void)
2853{
2854 if (!ISSET(MODIFIED)) {
2855 SET(MODIFIED);
2856 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002857 }
2858}
2859
2860void statusbar(const char *msg, ...)
2861{
2862 va_list ap;
2863
2864 va_start(ap, msg);
2865
2866 /* Curses mode is turned off. If we use wmove() now, it will muck
2867 * up the terminal settings. So we just use vfprintf(). */
2868 if (curses_ended) {
2869 vfprintf(stderr, msg, ap);
2870 va_end(ap);
2871 return;
2872 }
2873
2874 /* Blank out the line. */
2875 blank_statusbar();
2876
2877 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002878 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002879 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002880#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002881 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002882
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002883 UNSET(WHITESPACE_DISPLAY);
2884#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002885 bar = charalloc(mb_cur_max() * (COLS - 3));
2886 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002887 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002888 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002889#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2890 if (old_whitespace)
2891 SET(WHITESPACE_DISPLAY);
2892#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002893 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002894 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002895 start_x = (COLS - foo_len - 4) / 2;
2896
2897 wmove(bottomwin, 0, start_x);
2898 wattron(bottomwin, A_REVERSE);
2899
2900 waddstr(bottomwin, "[ ");
2901 waddstr(bottomwin, foo);
2902 free(foo);
2903 waddstr(bottomwin, " ]");
2904 wattroff(bottomwin, A_REVERSE);
2905 wnoutrefresh(bottomwin);
2906 reset_cursor();
2907 wrefresh(edit);
2908 /* Leave the cursor at its position in the edit window, not
2909 * in the statusbar. */
2910 }
2911
2912 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002913 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002914}
2915
Chris Allegretta6232d662002-05-12 19:52:15 +00002916void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002917{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002918 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002919
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002920 if (ISSET(NO_HELP))
2921 return;
2922
Chris Allegretta6232d662002-05-12 19:52:15 +00002923 if (s == main_list) {
2924 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002925 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002926 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002927 slen = length_of_list(s);
2928
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002929 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002930 if (slen > MAIN_VISIBLE)
2931 slen = MAIN_VISIBLE;
2932 }
2933
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002934 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002935 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002936 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002937
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002938 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002939
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002940 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002941 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002942
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002943 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002944#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002945 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002946 keystr = _("Up");
2947 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002948#endif
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00002949 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002950
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002951 if (s->ctrlval == NANO_CONTROL_SPACE)
2952 strcpy(foo, "^ ");
2953 else if (s->ctrlval == NANO_CONTROL_8)
2954 strcpy(foo, "^?");
2955 /* Normal values. Assume that the shortcut has an
2956 * equivalent control key, meta key sequence, or both. */
2957 else if (s->ctrlval != NANO_NO_KEY)
2958 sprintf(foo, "^%c", s->ctrlval + 64);
2959 else if (s->metaval != NANO_NO_KEY)
2960 sprintf(foo, "M-%c", toupper(s->metaval));
2961
2962 keystr = foo;
2963#ifndef NANO_SMALL
2964 }
2965#endif
2966
2967 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002968 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002969 }
2970
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002971 wnoutrefresh(bottomwin);
2972 reset_cursor();
2973 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002974}
2975
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002976/* Write a shortcut key to the help area at the bottom of the window.
2977 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2978 * to write at most len characters, even if len is very small and
2979 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2980 * the whole string! We do not bother padding the entry with blanks. */
2981void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002982{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002983 size_t keystroke_len = strlenpt(keystroke) + 1;
2984
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002985 assert(keystroke != NULL && desc != NULL);
2986
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002987 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002988 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002989 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002990
2991 if (len > keystroke_len)
2992 len -= keystroke_len;
2993 else
2994 len = 0;
2995
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002996 if (len > 0) {
2997 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002998 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002999 }
3000}
3001
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003002/* And so start the display update routines. */
3003
3004#ifndef NDEBUG
3005int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003006{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003007 int check_line = 0;
3008 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00003009
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003010 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
3011 check_line++;
3012 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00003013}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003014#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00003015
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003016/* nano scrolls horizontally within a line in chunks. This function
3017 * returns the column number of the first character displayed in the
3018 * window when the cursor is at the given column. Note that
3019 * 0 <= column - get_page_start(column) < COLS. */
3020size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00003021{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003022 assert(COLS > 0);
3023 if (column == 0 || column < COLS - 1)
3024 return 0;
3025 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00003026 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003027 else if (COLS > 2)
3028 return column - (COLS - 2);
3029 else
3030 return column - (COLS - 1);
3031 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003032}
3033
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003034/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003035 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003036void reset_cursor(void)
3037{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003038 /* If we haven't opened any files yet, put the cursor in the top
3039 * left corner of the edit window and get out. */
3040 if (edittop == NULL || current == NULL) {
3041 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003042 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003043 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003044
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003045 current_y = current->lineno - edittop->lineno;
3046 if (current_y < editwinrows) {
3047 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003048 wmove(edit, current_y, x - get_page_start(x));
3049 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003050}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003051
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003052/* edit_add() takes care of the job of actually painting a line into the
3053 * edit window. fileptr is the line to be painted, at row yval of the
3054 * window. converted is the actual string to be written to the window,
3055 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003056 * characters. start is the column number of the first character of
3057 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003058 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003059void edit_add(const filestruct *fileptr, const char *converted, int
3060 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003061{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003062#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003063 size_t startpos = actual_x(fileptr->data, start);
3064 /* The position in fileptr->data of the leftmost character
3065 * that displays at least partially on the window. */
3066 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3067 /* The position in fileptr->data of the first character that is
3068 * completely off the window to the right.
3069 *
3070 * Note that endpos might be beyond the null terminator of the
3071 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003072#endif
3073
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003074 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003075 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003076
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003077 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003078 * just the text that needs it). */
3079 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003080
Chris Allegretta7dd77682001-12-08 19:52:28 +00003081#ifdef ENABLE_COLOR
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003082 if (colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003083 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003084
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003085 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3086 int x_start;
3087 /* Starting column for mvwaddnstr. Zero-based. */
3088 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003089 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003090 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003091 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003092 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003093 regmatch_t startmatch; /* match position for start_regexp */
3094 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003095
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003096 if (tmpcolor->bright)
3097 wattron(edit, A_BOLD);
3098 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003099 /* Two notes about regexec(). Return value 0 means there is
3100 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003101 * after the match. */
3102
3103 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003104 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003105 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003106
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003107 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003108 * last match. Even though two matches may overlap, we
3109 * want to ignore them, so that we can highlight
3110 * C-strings correctly. */
3111 while (k < endpos) {
3112 /* Note the fifth parameter to regexec(). It says
3113 * not to match the beginning-of-line character
3114 * unless k is 0. If regexec() returns REG_NOMATCH,
3115 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003116 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003117 &startmatch, (k == 0) ? 0 :
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003118 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003119 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003120 /* Translate the match to the beginning of the
3121 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003122 startmatch.rm_so += k;
3123 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003124 if (startmatch.rm_so == startmatch.rm_eo) {
3125 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003126 statusbar(
3127 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003128 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003129 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003130 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003131 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003132 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003133 x_start = strnlenpt(fileptr->data,
3134 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003135
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003136 index = actual_x(converted, x_start);
3137
3138 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003139 strnlenpt(fileptr->data,
3140 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003141
3142 assert(0 <= x_start && 0 <= paintlen);
3143
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003144 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003145 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003146 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003147 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003148 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003149 } else {
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003150 /* This is a multi-line regexp. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003151 * First, we have to see if the beginning of the line is
3152 * colored by a start on an earlier line, and an end on
3153 * this line or later.
3154 *
3155 * We find the first line before fileptr matching the
3156 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003157 * end, then go to step two. Otherwise, find the next
3158 * line after start_line matching the end. If that line
3159 * is not before fileptr, then paint the beginning of
3160 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003161 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003162 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003163 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003164 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003165 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003166
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003167 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003168 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003169 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003170 /* If there is an end on this line, there is no need
3171 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003172 if (regexec(tmpcolor->end, start_line->data, 0,
3173 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003174 goto step_two;
3175 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003176 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003177 /* No start found, so skip to the next step. */
3178 if (start_line == NULL)
3179 goto step_two;
3180 /* Now start_line is the first line before fileptr
3181 * containing a start match. Is there a start on this
3182 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003183 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003184 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003185 start_col += startmatch.rm_so;
3186 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003187 if (regexec(tmpcolor->end, start_line->data +
3188 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003189 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003190 REG_NOTBOL) == REG_NOMATCH)
3191 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003192 break;
3193 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003194 if (regexec(&tmpcolor->start, start_line->data +
3195 start_col, 1, &startmatch,
3196 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003197 /* No later start on this line. */
3198 goto step_two;
3199 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003200 /* Indeed, there is a start not followed on this line by
3201 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003202
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003203 /* We have already checked that there is no end before
3204 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003205 * the start at all? We don't paint unterminated
3206 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003207 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003208 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003209 regexec(tmpcolor->end, end_line->data, 1,
3210 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003211 end_line = end_line->next;
3212
3213 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003214 if (end_line == NULL || (end_line == fileptr &&
3215 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003216 goto step_two;
3217
3218 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003219 if (end_line != fileptr)
3220 /* If the start of fileptr is on a different line
3221 * from the end, paintlen is -1, meaning that
3222 * everything on the line gets painted. */
3223 paintlen = -1;
3224 else
3225 /* Otherwise, paintlen is the expanded location of
3226 * the end of the match minus the expanded location
3227 * of the beginning of the page. */
3228 paintlen = actual_x(converted,
3229 strnlenpt(fileptr->data, endmatch.rm_eo) -
3230 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003231
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003232 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003233
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003234 step_two:
3235 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003236 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003237
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003238 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003239 if (regexec(&tmpcolor->start,
3240 fileptr->data + start_col, 1, &startmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003241 (start_col == 0) ? 0 :
3242 REG_NOTBOL) == REG_NOMATCH ||
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003243 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003244 /* No more starts on this line. */
3245 break;
3246 /* Translate the match to be relative to the
3247 * beginning of the line. */
3248 startmatch.rm_so += start_col;
3249 startmatch.rm_eo += start_col;
3250
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003251 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003252 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003253 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003254 x_start = strnlenpt(fileptr->data,
3255 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003256
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003257 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003258
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003259 if (regexec(tmpcolor->end,
3260 fileptr->data + startmatch.rm_eo, 1, &endmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003261 (startmatch.rm_eo == 0) ? 0 :
3262 REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003263 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003264 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003265 endmatch.rm_so += startmatch.rm_eo;
3266 endmatch.rm_eo += startmatch.rm_eo;
3267 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003268 * appear on this page, and is the match more
3269 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003270 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003271 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003272 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003273 strnlenpt(fileptr->data,
3274 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003275
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003276 assert(0 <= x_start && x_start < COLS);
3277
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003278 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003279 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003280 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003281 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003282 /* There is no end on this line. But we haven't
3283 * yet looked for one on later lines. */
3284 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003285
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003286 while (end_line != NULL &&
3287 regexec(tmpcolor->end, end_line->data,
3288 0, NULL, 0) == REG_NOMATCH)
3289 end_line = end_line->next;
3290
3291 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003292 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003293
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003294 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003295 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003296 /* We painted to the end of the line, so
3297 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003298 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003299 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003300 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003301 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003302 }
3303 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003304
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003305 wattroff(edit, A_BOLD);
3306 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003307 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003308 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003309#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003310
Chris Allegretta7dd77682001-12-08 19:52:28 +00003311#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003312 if (ISSET(MARK_ISSET)
3313 && (fileptr->lineno <= mark_beginbuf->lineno
3314 || fileptr->lineno <= current->lineno)
3315 && (fileptr->lineno >= mark_beginbuf->lineno
3316 || fileptr->lineno >= current->lineno)) {
3317 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003318
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003319 const filestruct *top;
3320 /* Either current or mark_beginbuf, whichever is first. */
3321 size_t top_x;
3322 /* current_x or mark_beginx, corresponding to top. */
3323 const filestruct *bot;
3324 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003325 int x_start;
3326 /* Starting column for mvwaddnstr. Zero-based. */
3327 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003328 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003329 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003330 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003331 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003332
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003333 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003334
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003335 if (top->lineno < fileptr->lineno || top_x < startpos)
3336 top_x = startpos;
3337 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3338 bot_x = endpos;
3339
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003340 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003341 if (top_x < endpos && bot_x > startpos) {
3342 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003343
3344 /* x_start is the expanded location of the beginning of the
3345 * mark minus the beginning of the page. */
3346 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003347
3348 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003349 /* If the end of the mark is off the page, paintlen is
3350 * -1, meaning that everything on the line gets
3351 * painted. */
3352 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003353 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003354 /* Otherwise, paintlen is the expanded location of the
3355 * end of the mark minus the expanded location of the
3356 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003357 paintlen = strnlenpt(fileptr->data, bot_x) -
3358 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003359
3360 /* If x_start is before the beginning of the page, shift
3361 * paintlen x_start characters to compensate, and put
3362 * x_start at the beginning of the page. */
3363 if (x_start < 0) {
3364 paintlen += x_start;
3365 x_start = 0;
3366 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003367
3368 assert(x_start >= 0 && x_start <= strlen(converted));
3369
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003370 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003371
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003372 if (paintlen > 0)
3373 paintlen = actual_x(converted + index, paintlen);
3374
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003375 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003376 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003377 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003378 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003379 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003380 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003381#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003382}
3383
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003384/* Just update one line in the edit buffer. This is basically a wrapper
3385 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003386 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003387 * If fileptr != current, then index is considered 0. The line will be
3388 * displayed starting with fileptr->data[index]. Likely args are
3389 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003390void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003391{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003392 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003393 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003394 char *converted;
3395 /* fileptr->data converted to have tabs and control characters
3396 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003397 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003398
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003399 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003400
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003401 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003402
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003403 /* We assume the line numbers are valid. Is that really true? */
3404 assert(line < 0 || line == check_linenumbers(fileptr));
3405
3406 if (line < 0 || line >= editwinrows)
3407 return;
3408
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003409 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003410 mvwaddstr(edit, line, 0, hblank);
3411
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003412 /* Next, convert variables that index the line to their equivalent
3413 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003414 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003415 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003416
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003417 /* Expand the line, replacing tabs with spaces, and control
3418 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003419 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003420
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003421 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003422 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003423 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003424
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003425 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003426 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003427 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003428 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003429}
3430
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003431/* Return a nonzero value if we need an update after moving
3432 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003433 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003434int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003435{
3436 return
3437#ifndef NANO_SMALL
3438 ISSET(MARK_ISSET) ||
3439#endif
3440 get_page_start(old_pww) != get_page_start(placewewant);
3441}
3442
3443/* Return a nonzero value if we need an update after moving vertically.
3444 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003445 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003446int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003447{
3448 return
3449#ifndef NANO_SMALL
3450 ISSET(MARK_ISSET) ||
3451#endif
3452 get_page_start(old_pww) != get_page_start(placewewant);
3453}
3454
3455/* Scroll the edit window in the given direction and the given number
3456 * of lines, and draw new lines on the blank lines left after the
3457 * scrolling. direction is the direction to scroll, either UP or DOWN,
3458 * and nlines is the number of lines to scroll. Don't redraw the old
3459 * topmost or bottommost line (where we assume current is) before
3460 * scrolling or draw the new topmost or bottommost line after scrolling
3461 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003462 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003463void edit_scroll(updown direction, int nlines)
3464{
3465 filestruct *foo;
3466 int i, scroll_rows = 0;
3467
3468 /* Scrolling less than one line or more than editwinrows lines is
3469 * redundant, so don't allow it. */
3470 if (nlines < 1 || nlines > editwinrows)
3471 return;
3472
3473 /* Move the top line of the edit window up or down (depending on the
3474 * value of direction) nlines lines. If there are fewer lines of
3475 * text than that left, move it to the top or bottom line of the
3476 * file (depending on the value of direction). Keep track of
3477 * how many lines we moved in scroll_rows. */
3478 for (i = nlines; i > 0; i--) {
3479 if (direction == UP) {
3480 if (edittop->prev == NULL)
3481 break;
3482 edittop = edittop->prev;
3483 scroll_rows--;
3484 } else {
3485 if (edittop->next == NULL)
3486 break;
3487 edittop = edittop->next;
3488 scroll_rows++;
3489 }
3490 }
3491
3492 /* Scroll the text on the screen up or down scroll_rows lines,
3493 * depending on the value of direction. */
3494 scrollok(edit, TRUE);
3495 wscrl(edit, scroll_rows);
3496 scrollok(edit, FALSE);
3497
3498 foo = edittop;
3499 if (direction != UP) {
3500 int slines = editwinrows - nlines;
3501 for (; slines > 0 && foo != NULL; slines--)
3502 foo = foo->next;
3503 }
3504
3505 /* And draw new lines on the blank top or bottom lines of the edit
3506 * window, depending on the value of direction. Don't draw the new
3507 * topmost or new bottommost line. */
3508 while (scroll_rows != 0 && foo != NULL) {
3509 if (foo->next != NULL)
3510 update_line(foo, 0);
3511 if (direction == UP)
3512 scroll_rows++;
3513 else
3514 scroll_rows--;
3515 foo = foo->next;
3516 }
3517}
3518
3519/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003520 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003521void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003522{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003523 int do_refresh = need_vertical_update(0) ||
3524 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003525 const filestruct *foo;
3526
3527 /* If either old_current or current is offscreen, refresh the screen
3528 * and get out. */
3529 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3530 edittop->lineno + editwinrows || current->lineno <
3531 edittop->lineno || current->lineno >= edittop->lineno +
3532 editwinrows) {
3533 edit_refresh();
3534 return;
3535 }
3536
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003537 /* Update old_current and current if we're not on the first page
3538 * and/or we're not on the same page as before. If the mark is on,
3539 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003540 foo = old_current;
3541 while (foo != current) {
3542 if (do_refresh)
3543 update_line(foo, 0);
3544#ifndef NANO_SMALL
3545 if (!ISSET(MARK_ISSET))
3546#endif
3547 break;
3548 if (foo->lineno > current->lineno)
3549 foo = foo->prev;
3550 else
3551 foo = foo->next;
3552 }
3553 if (do_refresh)
3554 update_line(current, current_x);
3555}
3556
Chris Allegretta6df90f52002-07-19 01:08:59 +00003557/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003558void edit_refresh(void)
3559{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003560 if (current->lineno < edittop->lineno ||
3561 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003562 /* Note that edit_update() changes edittop so that it's in range
3563 * of current. Thus, when it then calls edit_refresh(), there
3564 * is no danger of getting an infinite loop. */
3565 edit_update(
3566#ifndef NANO_SMALL
3567 ISSET(SMOOTHSCROLL) ? NONE :
3568#endif
3569 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003570 else {
3571 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003572 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003573
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003574#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003575 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003576#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003577
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003578 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003579 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003580 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003581 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003582 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003583 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003584 }
3585 while (nlines < editwinrows) {
3586 mvwaddstr(edit, nlines, 0, hblank);
3587 nlines++;
3588 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003589 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003590 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003591 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003592}
3593
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003594/* A nice generic routine to update the edit buffer. We keep current in
3595 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003596void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003597{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003598 filestruct *foo = current;
3599
Chris Allegretta6df90f52002-07-19 01:08:59 +00003600 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003601 /* If location is CENTER, we move edittop up (editwinrows / 2)
3602 * lines. This puts current at the center of the screen. If
3603 * location is NONE, we move edittop up current_y lines if
3604 * current_y is in range of the screen, 0 lines if current_y is
3605 * less than 0, or (editwinrows - 1) lines if current_y is
3606 * greater than (editwinrows - 1). This puts current at the
3607 * same place on the screen as before, or at the top or bottom
3608 * of the screen if edittop is beyond either. */
3609 int goal;
3610
3611 if (location == CENTER)
3612 goal = editwinrows / 2;
3613 else {
3614 goal = current_y;
3615
3616 /* Limit goal to (editwinrows - 1) lines maximum. */
3617 if (goal > editwinrows - 1)
3618 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003619 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003620
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003621 for (; goal > 0 && foo->prev != NULL; goal--)
3622 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003623 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003624
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003625 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003626 edit_refresh();
3627}
3628
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003629/* Ask a simple yes/no question, specified in msg, on the statusbar.
3630 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3631 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003632int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003633{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003634 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003635 const char *yesstr; /* String of yes characters accepted. */
3636 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003637 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003638
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003639 /* yesstr, nostr, and allstr are strings of any length. Each string
3640 * consists of all characters accepted as a valid character for that
3641 * value. The first value will be the one displayed in the
3642 * shortcuts. Translators: if possible, specify both the shortcuts
3643 * for your language and English. For example, in French: "OoYy"
3644 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003645 yesstr = _("Yy");
3646 nostr = _("Nn");
3647 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003648
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003649 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003650 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003651
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003652 if (COLS < 32)
3653 width = COLS / 2;
3654
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003655 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003656 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003657
Chris Allegretta6232d662002-05-12 19:52:15 +00003658 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003659 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003660 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003661
3662 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003663 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003664 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003665 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003666 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003667
Chris Allegrettadb28e962003-01-28 01:23:40 +00003668 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003669 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003670 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003671
Chris Allegrettadb28e962003-01-28 01:23:40 +00003672 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003673 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003674 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003675
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003676 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003677
3678 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003679 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003680
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003681 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003682
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003683 wrefresh(bottomwin);
3684
Chris Allegrettadb28e962003-01-28 01:23:40 +00003685 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003686 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003687 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003688#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003689 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003690#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003691
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003692 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003693
3694 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003695 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003696#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003697 /* Look, ma! We get to duplicate lots of code from
3698 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003699 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003700 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003701
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003702 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003703 wenclose(bottomwin, mouse_y, mouse_x) &&
3704 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003705 int x = mouse_x / width;
3706 /* Did we click in the first column of shortcuts, or
3707 * the second? */
3708 int y = mouse_y - editwinrows - 3;
3709 /* Did we click in the first row of shortcuts? */
3710
3711 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3712
3713 /* x = 0 means they clicked Yes or No.
3714 * y = 0 means Yes or All. */
3715 ok = -2 * x * y + x - y + 1;
3716
3717 if (ok == 2 && !all)
3718 ok = -2;
3719 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003720 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003721#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003722 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003723 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003724 else if (strchr(yesstr, kbinput) != NULL)
3725 ok = 1;
3726 else if (strchr(nostr, kbinput) != NULL)
3727 ok = 0;
3728 else if (all && strchr(allstr, kbinput) != NULL)
3729 ok = 2;
3730 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003731
Chris Allegrettadb28e962003-01-28 01:23:40 +00003732 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003733}
3734
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003735void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003736{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003737 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003738 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003739 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003740 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003741 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003742 wnoutrefresh(bottomwin);
3743 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003744 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003745 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003746 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003747 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003748 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003749 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003750}
3751
3752void display_main_list(void)
3753{
3754 bottombars(main_list);
3755}
3756
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003757/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3758 * display the cursor position. Otherwise, we display it only if the
3759 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003760 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003761 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3762 * old_i and old_totsize. That way, we leave the current statusbar
3763 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003764void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003765{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003766 char c;
3767 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003768 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003769 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003770
Chris Allegrettad26ab912003-01-28 01:16:47 +00003771 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003772
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003773 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003774 old_totsize = totsize;
3775
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003776 c = current->data[current_x];
3777 f = current->next;
3778 current->data[current_x] = '\0';
3779 current->next = NULL;
3780 get_totals(fileage, current, NULL, &i);
3781 current->data[current_x] = c;
3782 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003783
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003784 /* Check whether totsize is correct. Else there is a bug
3785 * somewhere. */
3786 assert(current != filebot || i == totsize);
3787
Chris Allegrettad26ab912003-01-28 01:16:47 +00003788 if (constant && ISSET(DISABLE_CURPOS)) {
3789 UNSET(DISABLE_CURPOS);
3790 old_i = i;
3791 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003792 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003793 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003794
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003795 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003796 * unconditionally; otherwise, only display the position when the
3797 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003798 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003799 size_t xpt = xplustabs() + 1;
3800 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003801 int linepct = 100 * current->lineno / totlines;
3802 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003803 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003804
3805 statusbar(
3806 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3807 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003808 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003809 (unsigned long)i, (unsigned long)totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003810 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003811 }
3812
3813 old_i = i;
3814 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003815}
3816
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003817void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003818{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003819 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003820}
3821
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003822#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003823/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003824int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003825{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003826 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003827
3828 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3829 ptr++;
3830 j++;
3831 }
3832 if (j == COLS - 5) {
3833 /* Don't wrap at the first of two spaces following a period. */
3834 if (*ptr == ' ' && *(ptr + 1) == ' ')
3835 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003836 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003837 while (*ptr != ' ' && j > 0) {
3838 ptr--;
3839 j--;
3840 }
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003841 /* A word longer than (COLS - 5) chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003842 if (j == 0)
3843 j = COLS - 5;
3844 }
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003845
Chris Allegretta4640fe32003-02-10 03:10:03 +00003846 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003847
Chris Allegretta4640fe32003-02-10 03:10:03 +00003848 return j;
3849}
3850
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003851/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003852void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003853{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003854 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003855 /* The line number in help_text of the first displayed help
3856 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003857 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003858 /* no_more means the end of the help text is shown, so don't go
3859 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003860 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003861 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003862
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003863 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003864#ifndef DISABLE_MOUSE
3865 const shortcut *oldshortcut = currshortcut;
3866 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003867 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003868#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003869
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003870 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003871 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003872 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003873 blank_statusbar();
3874
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003875 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003876 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003877 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003878
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003879#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003880 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003881 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003882 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003883#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003884
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003885 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003886 /* Make sure that the help screen's shortcut list will actually
3887 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003888 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003889 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003890 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003891
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003892 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003893
3894 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003895 int i;
3896 int old_line = line;
3897 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003898 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003899
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003900 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003901#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003902 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003903 {
3904 int mouse_x, mouse_y;
3905 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3906 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003907 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003908#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003909 case NANO_NEXTPAGE_KEY:
3910 case NANO_NEXTPAGE_FKEY:
3911 if (!no_more)
3912 line += editwinrows - 2;
3913 break;
3914 case NANO_PREVPAGE_KEY:
3915 case NANO_PREVPAGE_FKEY:
3916 if (line > 0) {
3917 line -= editwinrows - 2;
3918 if (line < 0)
3919 line = 0;
3920 }
3921 break;
3922 case NANO_PREVLINE_KEY:
3923 if (line > 0)
3924 line--;
3925 break;
3926 case NANO_NEXTLINE_KEY:
3927 if (!no_more)
3928 line++;
3929 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003930 }
3931
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003932 if (line == old_line && kbinput != ERR)
3933 goto skip_redisplay;
3934
3935 blank_edit();
3936
3937 assert(COLS > 5);
3938
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003939 /* Calculate where in the text we should be, based on the
3940 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003941 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003942 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003943 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003944 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003945 }
3946
Chris Allegretta4640fe32003-02-10 03:10:03 +00003947 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003948 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003949
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003950 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003951 ptr += j;
3952 if (*ptr == '\n')
3953 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003954 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003955 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003956
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003957 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003958 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003959 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3960 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003961
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003962#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003963 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003964#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003965
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003966 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003967 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003968 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003969 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003970 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003971 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003972 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003973
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003974 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003975 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003976
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003977 /* The help_init() at the beginning allocated help_text. Since
3978 * help_text has now been written to the screen, we don't need it
3979 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003980 free(help_text);
3981 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003982}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003983#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003984
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003985/* Highlight the current word being replaced or spell checked. We
3986 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003987void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003988{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003989 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003990 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003991
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003992 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003993 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003994 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003995
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003996 assert(y > 0);
3997
3998 if (word_len > y)
3999 y--;
4000
Chris Allegrettafb62f732000-12-05 11:36:41 +00004001 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00004002
Chris Allegrettafb62f732000-12-05 11:36:41 +00004003 if (highlight_flag)
4004 wattron(edit, A_REVERSE);
4005
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004006#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00004007 /* This is so we can show zero-length regexes. */
4008 if (word_len == 0)
4009 waddstr(edit, " ");
4010 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004011#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004012 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004013
4014 if (word_len > y)
4015 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00004016
4017 if (highlight_flag)
4018 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004019}
4020
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004021#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004022/* Dump the passed-in file structure to stderr. */
4023void dump_buffer(const filestruct *inptr)
4024{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004025 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004026 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004027 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004028 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004029 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00004030 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004031
4032 while (inptr != NULL) {
4033 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4034 inptr = inptr->next;
4035 }
4036}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004037
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004038/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004039void dump_buffer_reverse(void)
4040{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004041 const filestruct *fileptr = filebot;
4042
4043 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004044 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004045 fileptr = fileptr->prev;
4046 }
4047}
4048#endif /* DEBUG */
4049
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004050#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004051#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004052#define XLCREDIT_LEN 8
4053
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004054/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004055void do_credits(void)
4056{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004057 int crpos = 0, xlpos = 0;
4058 const char *credits[CREDIT_LEN] = {
4059 NULL, /* "The nano text editor" */
4060 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004061 VERSION,
4062 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004063 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004064 "Chris Allegretta",
4065 "Jordi Mallach",
4066 "Adam Rogoyski",
4067 "Rob Siemborski",
4068 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004069 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004070 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004071 "Ken Tyler",
4072 "Sven Guckes",
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004073 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00004074 "Pauli Virtanen",
4075 "Daniele Medri",
4076 "Clement Laforet",
4077 "Tedi Heriyanto",
4078 "Bill Soudan",
4079 "Christian Weisgerber",
4080 "Erik Andersen",
4081 "Big Gaute",
4082 "Joshua Jensen",
4083 "Ryan Krebs",
4084 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004085 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004086 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004087 "Plattsburgh State University",
4088 "Benet Laboratories",
4089 "Amy Allegretta",
4090 "Linda Young",
4091 "Jeremy Robichaud",
4092 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004093 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004094 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004095 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004096 "Thomas Dickey",
4097 "Pavel Curtis",
4098 "Zeyd Ben-Halim",
4099 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004100 NULL, /* "and anyone else we forgot..." */
4101 NULL, /* "Thank you for using nano!" */
4102 "",
4103 "",
4104 "",
4105 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004106 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004107 "",
4108 "",
4109 "",
4110 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004111 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004112 };
4113
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004114 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004115 N_("The nano text editor"),
4116 N_("version"),
4117 N_("Brought to you by:"),
4118 N_("Special thanks to:"),
4119 N_("The Free Software Foundation"),
4120 N_("For ncurses:"),
4121 N_("and anyone else we forgot..."),
4122 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004123 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004124
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004125 curs_set(0);
4126 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004127 scrollok(edit, TRUE);
4128 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004129 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004130 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004131 blank_statusbar();
4132 blank_bottombars();
4133 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004134 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004135 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004136
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004137 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
4138 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004139 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004140
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004141 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004142 char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004143 size_t start_x;
4144
David Lawrence Ramsey631242d2005-03-15 07:06:54 +00004145 /* Make sure every credit is a valid multibyte string, since
4146 * we can't dynamically set the credits to their multibyte
4147 * equivalents when we need to. Sigh... */
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004148 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004149 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004150
4151 what = mallocstrcpy(NULL, _(xlcredits[xlpos]));
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004152 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004153 } else
4154 what = make_mbstring(credits[crpos]);
4155
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004156 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004157 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
4158 start_x, what);
4159
4160 free(what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004161 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004162
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004163 napms(700);
4164 scroll(edit);
4165 wrefresh(edit);
4166 if (wgetch(edit) != ERR)
4167 break;
4168 napms(700);
4169 scroll(edit);
4170 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004171 }
4172
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004173 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004174 nodelay(edit, FALSE);
4175 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004176 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004177}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004178#endif