blob: 619a4c7dab115f1db9ca9b539ee89d3742297c6e [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 Ramsey93c4a562004-12-23 21:32:27 +000035#if defined(HAVE_WCHAR_H) && defined(NANO_WIDE)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +000036#include <wchar.h>
37#endif
38
David Lawrence Ramsey74835712004-12-04 17:41:52 +000039static buffer *key_buffer = NULL;
40 /* The default keystroke buffer,
41 * containing all the keystrokes we have
42 * at a given point. */
43static size_t key_buffer_len = 0;
44 /* The length of the default keystroke
45 * buffer. */
46static int statusblank = 0; /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000047 * we call statusbar(), before we
48 * actually blank the statusbar. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +000049static size_t statusbar_x = (size_t)-1;
50 /* The cursor position in answer. */
51static size_t statusbar_xend = 0;
52 /* The length of answer. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000053static bool resetstatuspos = FALSE;
54 /* Should we reset the cursor position
55 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000056
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000057/* Control character compatibility:
58 *
59 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
60 * VT100, and VT220.
61 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
62 * VT220, and VT320.
63 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
64 * VT220, and VT320.
65 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
66 * VT220, and VT320.
67 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
68 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000069 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000070 * ANSI, VT100, and VT220, and which is Backspace under VT320.
71 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000072 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000073 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
74 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000075 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000076 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000077 * on which the VT320 sequences are translated by the keypad to KEY_DC
78 * and [nothing]. We work around this conflict via the REBIND_DELETE
79 * flag: if it's not set, we assume VT320 compatibility, and if it is,
80 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
81 * Hemel for helping work this conflict out.
82 *
83 * Escape sequence compatibility:
84 *
85 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000086 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000087 * console), xterm, rxvt, and Eterm. Among these, there are several
88 * conflicts and omissions, outlined as follows:
89 *
90 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
91 * (Ctrl-I is also Tab on ANSI, which we already support.)
92 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
93 * NumLock off on Linux console; the latter is omitted. (The editing
94 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000095 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000096 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
97 * latter is omitted. (Mouse input will only work properly if the
98 * extended keypad value KEY_MOUSE is generated on mouse events
99 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000100 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000101 * omitted. (The editing keypad is more important to have working
102 * than the function keys, because the functions of the former are not
103 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000104 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000105 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000106 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000107 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000108 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
109 * omitted. (The arrow keys, with or without modifiers, are more
110 * important to have working than the function keys, because the
111 * functions of the former are not arbitrary and the functions of the
112 * latter are.)
113 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
114 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000115 *
116 * Note that Center (5) on the numeric keypad with NumLock off can also
117 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000118
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000119#ifndef NANO_SMALL
120/* Reset all the input routines that rely on character sequences. */
121void reset_kbinput(void)
122{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000123 parse_kbinput(NULL, NULL, NULL, TRUE);
124 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000125}
126#endif
127
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000128/* Read in a sequence of keystrokes from win and save them in the
129 * default keystroke buffer. This should only be called when the
130 * default keystroke buffer is empty. */
131void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000132{
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000133 int input, input_key_code;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000134
135 /* If the keystroke buffer isn't empty, get out. */
136 if (key_buffer != NULL)
137 return;
138
139 /* Read in the first character using blocking input. */
140 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000141
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000142#ifndef NANO_SMALL
143 allow_pending_sigwinch(TRUE);
144#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000145
146#ifdef NANO_WIDE
147 if (!ISSET(NO_UTF8)) {
148 wint_t tmp;
149
150 input_key_code = wget_wch(win, &tmp);
151 input = (int)tmp;
152 } else {
153#endif
154 input = wgetch(win);
155 input_key_code = !is_byte_char(input);
156#ifdef NANO_WIDE
157 }
158#endif
159
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000160#ifndef NANO_SMALL
161 allow_pending_sigwinch(FALSE);
162#endif
163
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000164 /* Increment the length of the keystroke buffer, save the value of
165 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000166 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000167 key_buffer_len++;
168 key_buffer = (buffer *)nmalloc(sizeof(buffer));
169 key_buffer[0].key = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000170 key_buffer[0].key_code =
171#ifdef NANO_WIDE
172 !ISSET(NO_UTF8) ? (input_key_code == KEY_CODE_YES) :
173#endif
174 input_key_code;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000175
176 /* Read in the remaining characters using non-blocking input. */
177 nodelay(win, TRUE);
178
179 while (TRUE) {
180#ifndef NANO_SMALL
181 allow_pending_sigwinch(TRUE);
182#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000183
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000184#ifdef NANO_WIDE
185 if (!ISSET(NO_UTF8)) {
186 wint_t tmp;
187
188 input_key_code = wget_wch(win, &tmp);
189 input = (int)tmp;
190 } else {
191#endif
192 input = wgetch(win);
193 input_key_code = !is_byte_char(input);
194#ifdef NANO_WIDE
195 }
196#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000197 /* If there aren't any more characters, stop reading. */
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000198 if (
199#ifdef NANO_WIDE
200 (!ISSET(NO_UTF8) && input_key_code == ERR) ||
201#endif
202 input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000203 break;
204
205 /* Otherwise, increment the length of the keystroke buffer, save
206 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000207 * if the keystroke is an extended keypad value or FALSE if it
208 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000209 key_buffer_len++;
210 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
211 sizeof(buffer));
212 key_buffer[key_buffer_len - 1].key = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000213 key_buffer[key_buffer_len - 1].key_code =
214#ifdef NANO_WIDE
215 !ISSET(NO_UTF8) ? (input_key_code == KEY_CODE_YES) :
216#endif
217 input_key_code;
218
219#ifndef NANO_SMALL
220 allow_pending_sigwinch(FALSE);
221#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000222 }
223
224 /* Switch back to non-blocking input. */
225 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000226}
227
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000228/* Return the length of the default keystroke buffer. */
229size_t get_buffer_len(void)
230{
231 return key_buffer_len;
232}
233
234/* Return the key values stored in the keystroke buffer input,
235 * discarding the key_code values in it. */
236int *buffer_to_keys(buffer *input, size_t input_len)
237{
238 int *sequence = (int *)nmalloc(input_len * sizeof(int));
239 size_t i;
240
241 for (i = 0; i < input_len; i++)
242 sequence[i] = input[i].key;
243
244 return sequence;
245}
246
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +0000247/* Return the buffer equivalent of the key values in input, adding
248 * key_code values of FALSE to all of them. */
249buffer *keys_to_buffer(int *input, size_t input_len)
250{
251 buffer *sequence = (buffer *)nmalloc(input_len * sizeof(buffer));
252 size_t i;
253
254 for (i = 0; i < input_len; i++) {
255 sequence[i].key = input[i];
256 sequence[i].key_code = FALSE;
257 }
258
259 return sequence;
260}
261
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000262/* Add the contents of the keystroke buffer input to the default
263 * keystroke buffer. */
264void unget_input(buffer *input, size_t input_len)
265{
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000266 buffer *clean_input = NULL;
267 size_t clean_input_len = 0;
268
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000269#ifndef NANO_SMALL
270 allow_pending_sigwinch(TRUE);
271 allow_pending_sigwinch(FALSE);
272#endif
273
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000274#ifdef NANO_WIDE
275 if (!ISSET(NO_UTF8)) {
David Lawrence Ramseyf812e4f2004-12-07 17:35:14 +0000276 size_t i;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000277 char *key = charalloc(MB_CUR_MAX);
David Lawrence Ramsey60448892004-12-08 16:52:52 +0000278
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000279 /* Keep all valid wide keystrokes, discarding the others. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000280 for (i = 0; i < input_len; i++) {
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000281 int key_len = input[i].key_code ? 1 :
David Lawrence Ramseyc2ac02f2004-12-09 03:05:45 +0000282 wctomb(key, (wchar_t)input[i].key);
David Lawrence Ramseyeae97ca2004-12-07 22:24:03 +0000283
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000284 if (key_len != -1) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000285 clean_input_len++;
286 clean_input = (buffer *)nrealloc(clean_input,
287 clean_input_len * sizeof(buffer));
288
289 clean_input[clean_input_len - 1].key = input[i].key;
290 clean_input[clean_input_len - 1].key_code =
291 input[i].key_code;
292 }
293 }
David Lawrence Ramsey60448892004-12-08 16:52:52 +0000294
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000295 free(key);
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000296 } else {
297#endif
298 clean_input = input;
299 clean_input_len = input_len;
300#ifdef NANO_WIDE
301 }
302#endif
303
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000304 /* If input is empty, get out. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000305 if (clean_input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000306 return;
307
308 /* If adding input would put the default keystroke buffer beyond
309 * maximum capacity, only add enough of input to put it at maximum
310 * capacity. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000311 if (key_buffer_len + clean_input_len < key_buffer_len)
312 clean_input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000313
314 /* Add the length of input to the length of the default keystroke
315 * buffer, and reallocate the default keystroke buffer so that it
316 * has enough room for input. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000317 key_buffer_len += clean_input_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000318 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
319 sizeof(buffer));
320
321 /* If the default keystroke buffer wasn't empty before, move its
322 * beginning forward far enough so that we can add input to its
323 * beginning. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000324 if (key_buffer_len > clean_input_len)
325 memmove(key_buffer + clean_input_len, key_buffer,
326 (key_buffer_len - clean_input_len) * sizeof(buffer));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000327
328 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000329 memcpy(key_buffer, clean_input, clean_input_len * sizeof(buffer));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000330}
331
332/* Put back the character stored in kbinput. If func_key is TRUE and
333 * the character is out of byte range, interpret it as an extended
334 * keypad value. If meta_key is TRUE, put back the Escape character
335 * after putting back kbinput. */
336void unget_kbinput(int kbinput, bool meta_key, bool func_key)
337{
338 buffer input;
339
340 input.key = kbinput;
341 input.key_code = (func_key && !is_byte_char(kbinput));
342
343 unget_input(&input, 1);
344
345 if (meta_key) {
346 input.key = NANO_CONTROL_3;
347 input.key_code = FALSE;
348 unget_input(&input, 1);
349 }
350}
351
352/* Try to read input_len characters from the default keystroke buffer.
353 * If the default keystroke buffer is empty and win isn't NULL, try to
354 * read in more characters from win and add them to the default
355 * keystroke buffer before doing anything else. If the default
356 * keystroke buffer is empty and win is NULL, return NULL. */
357buffer *get_input(WINDOW *win, size_t input_len)
358{
359 buffer *input;
360
361#ifndef NANO_SMALL
362 allow_pending_sigwinch(TRUE);
363 allow_pending_sigwinch(FALSE);
364#endif
365
366 if (key_buffer_len == 0) {
367 if (win != NULL)
368 get_buffer(win);
369
370 if (key_buffer_len == 0)
371 return NULL;
372 }
373
374 /* If input_len is greater than the length of the default keystroke
375 * buffer, only read the number of characters in the default
376 * keystroke buffer. */
377 if (input_len > key_buffer_len)
378 input_len = key_buffer_len;
379
380 /* Subtract input_len from the length of the default keystroke
381 * buffer, and allocate the keystroke buffer input so that it
382 * has enough room for input_len keystrokes. */
383 key_buffer_len -= input_len;
384 input = (buffer *)nmalloc(input_len * sizeof(buffer));
385
386 /* Copy input_len characters from the beginning of the default
387 * keystroke buffer into input. */
388 memcpy(input, key_buffer, input_len * sizeof(buffer));
389
390 /* If the default keystroke buffer is empty, mark it as such. */
391 if (key_buffer_len == 0) {
392 free(key_buffer);
393 key_buffer = NULL;
394 /* If the default keystroke buffer isn't empty, move its
395 * beginning forward far enough back so that the keystrokes in input
396 * are no longer at its beginning. */
397 } else {
398 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
399 sizeof(buffer));
400 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
401 sizeof(buffer));
402 }
403
404 return input;
405}
406
407/* Read in a single character. If it's ignored, swallow it and go on.
408 * Otherwise, try to translate it from ASCII, meta key sequences, escape
409 * sequences, and/or extended keypad values. Set meta_key to TRUE when
410 * we get a meta key sequence, and set func_key to TRUE when we get an
411 * extended keypad value. Supported extended keypad values consist of
412 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
413 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
414 * the function keypad (F1-F16), and the numeric keypad with NumLock
415 * off. Assume nodelay(win) is FALSE. */
416int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
417{
418 int kbinput;
419
420 /* Read in a character and interpret it. Continue doing this until
421 * we get a recognized value or sequence. */
422 while ((kbinput = parse_kbinput(win, meta_key, func_key
423#ifndef NANO_SMALL
424 , FALSE
425#endif
426 )) == ERR);
427
428 return kbinput;
429}
430
431/* Translate ASCII characters, extended keypad values, and escape
432 * sequences into their corresponding key values. Set meta_key to TRUE
433 * when we get a meta key sequence, and set func_key to TRUE when we get
434 * a function key. Assume nodelay(win) is FALSE. */
435int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000436#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000437 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000438#endif
439 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000440
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000441{
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +0000442 static int escapes = 0, word_digits = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000443 buffer *kbinput;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000444 int retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000445
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000446 if (reset) {
447 escapes = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000448 word_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000449 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000450 }
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000451
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000452 *meta_key = FALSE;
453 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000454
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000455 /* Read in a character. */
456 while ((kbinput = get_input(win, 1)) == NULL);
457
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000458 if (kbinput->key_code || is_byte_char(kbinput->key)) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000459 /* If we got an extended keypad value or an ASCII character,
460 * translate it. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000461 switch (kbinput->key) {
462 case ERR:
463 break;
464 case NANO_CONTROL_3:
465 /* Increment the escape counter. */
466 escapes++;
467 switch (escapes) {
468 case 1:
469 /* One escape: wait for more input. */
470 case 2:
471 /* Two escapes: wait for more input. */
472 break;
473 default:
474 /* More than two escapes: reset the escape
475 * counter and wait for more input. */
476 escapes = 0;
477 }
478 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000479#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000480 /* Since we don't change the default SIGWINCH handler when
481 * NANO_SMALL is defined, KEY_RESIZE is never generated.
482 * Also, Slang and SunOS 5.7-5.9 don't support
483 * KEY_RESIZE. */
484 case KEY_RESIZE:
485 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000486#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000487#ifdef PDCURSES
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000488 case KEY_SHIFT_L:
489 case KEY_SHIFT_R:
490 case KEY_CONTROL_L:
491 case KEY_CONTROL_R:
492 case KEY_ALT_L:
493 case KEY_ALT_R:
494 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000495#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000496 default:
497 switch (escapes) {
498 case 0:
499 switch (kbinput->key) {
500 case NANO_CONTROL_8:
501 retval = ISSET(REBIND_DELETE) ?
502 NANO_DELETE_KEY :
503 NANO_BACKSPACE_KEY;
504 break;
505 case KEY_DOWN:
506 retval = NANO_NEXTLINE_KEY;
507 break;
508 case KEY_UP:
509 retval = NANO_PREVLINE_KEY;
510 break;
511 case KEY_LEFT:
512 retval = NANO_BACK_KEY;
513 break;
514 case KEY_RIGHT:
515 retval = NANO_FORWARD_KEY;
516 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000517#ifdef KEY_HOME
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000518 /* HP-UX 10 and 11 don't support
519 * KEY_HOME. */
520 case KEY_HOME:
521 retval = NANO_HOME_KEY;
522 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000523#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000524 case KEY_BACKSPACE:
525 retval = NANO_BACKSPACE_KEY;
526 break;
527 case KEY_DC:
528 retval = ISSET(REBIND_DELETE) ?
529 NANO_BACKSPACE_KEY :
530 NANO_DELETE_KEY;
531 break;
532 case KEY_IC:
533 retval = NANO_INSERTFILE_KEY;
534 break;
535 case KEY_NPAGE:
536 retval = NANO_NEXTPAGE_KEY;
537 break;
538 case KEY_PPAGE:
539 retval = NANO_PREVPAGE_KEY;
540 break;
541 case KEY_ENTER:
542 retval = NANO_ENTER_KEY;
543 break;
544 case KEY_A1: /* Home (7) on numeric
545 * keypad with NumLock
546 * off. */
547 retval = NANO_HOME_KEY;
548 break;
549 case KEY_A3: /* PageUp (9) on numeric
550 * keypad with NumLock
551 * off. */
552 retval = NANO_PREVPAGE_KEY;
553 break;
554 case KEY_B2: /* Center (5) on numeric
555 * keypad with NumLock
556 * off. */
557 break;
558 case KEY_C1: /* End (1) on numeric
559 * keypad with NumLock
560 * off. */
561 retval = NANO_END_KEY;
562 break;
563 case KEY_C3: /* PageDown (4) on
564 * numeric keypad with
565 * NumLock off. */
566 retval = NANO_NEXTPAGE_KEY;
567 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000568#ifdef KEY_BEG
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000569 /* Slang doesn't support KEY_BEG. */
570 case KEY_BEG: /* Center (5) on numeric
571 * keypad with NumLock
572 * off. */
573 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000574#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000575#ifdef KEY_END
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000576 /* HP-UX 10 and 11 don't support KEY_END. */
577 case KEY_END:
578 retval = NANO_END_KEY;
579 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000580#endif
581#ifdef KEY_SUSPEND
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000582 /* Slang doesn't support KEY_SUSPEND. */
583 case KEY_SUSPEND:
584 retval = NANO_SUSPEND_KEY;
585 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000586#endif
587#ifdef KEY_SLEFT
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000588 /* Slang doesn't support KEY_SLEFT. */
589 case KEY_SLEFT:
590 retval = NANO_BACK_KEY;
591 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000592#endif
593#ifdef KEY_SRIGHT
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000594 /* Slang doesn't support KEY_SRIGHT. */
595 case KEY_SRIGHT:
596 retval = NANO_FORWARD_KEY;
597 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000598#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000599 default:
600 retval = kbinput->key;
601 break;
602 }
603 break;
604 case 1:
605 /* One escape followed by a non-escape: escape
606 * sequence mode. Reset the escape counter. If
607 * there aren't any other keys waiting, we have
608 * a meta key sequence, so set meta_key to TRUE
609 * and save the lowercase version of the
610 * non-escape character as the result. If there
611 * are other keys waiting, we have a true escape
612 * sequence, so interpret it. */
613 escapes = 0;
614 if (get_buffer_len() == 0) {
615 *meta_key = TRUE;
616 retval = tolower(kbinput->key);
617 } else {
618 buffer *escape_kbinput;
619 int *sequence;
620 size_t seq_len;
621 bool ignore_seq;
622
623 /* Put back the non-escape character, get
624 * the complete escape sequence, translate
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +0000625 * the sequence into its corresponding key
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000626 * value, and save that as the result. */
627 unget_input(kbinput, 1);
628 seq_len = get_buffer_len();
629 escape_kbinput = get_input(NULL, seq_len);
630 sequence = buffer_to_keys(escape_kbinput,
631 seq_len);
632 retval = get_escape_seq_kbinput(sequence,
633 seq_len, &ignore_seq);
634
635 /* If the escape sequence is unrecognized
636 * and not ignored, put back all of its
637 * characters except for the initial
638 * escape. */
639 if (retval == ERR && !ignore_seq)
640 unget_input(escape_kbinput, seq_len);
641
642 free(escape_kbinput);
643 }
644 break;
645 case 2:
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000646 /* Two escapes followed by one or more decimal
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000647 * digits: word sequence mode. If the word
648 * sequence's range is limited to 6XXXX (the
649 * first digit is in the '0' to '6' range and
650 * it's the first digit, or it's in the '0' to
651 * '9' range and it's not the first digit),
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000652 * increment the word sequence counter and
653 * interpret the digit. If the word sequence's
654 * range is not limited to 6XXXX, fall
655 * through. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000656 if (('0' <= kbinput->key && kbinput->key <= '6'
657 && word_digits == 0) ||
658 ('0' <= kbinput->key && kbinput->key <= '9'
659 && word_digits > 0)) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000660 int word_kbinput;
661
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000662 word_digits++;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000663 word_kbinput = get_word_kbinput(kbinput->key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000664#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000665 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000666#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000667 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000668
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000669 if (word_kbinput != ERR) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000670 /* If we've read in a complete word
671 * sequence, reset the word sequence
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000672 * counter and the escape counter,
673 * and put back the corresponding word
674 * value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000675 word_digits = 0;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000676 escapes = 0;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000677 unget_kbinput(word_kbinput, FALSE,
678 FALSE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000679 }
680 } else {
681 /* Reset the escape counter. */
682 escapes = 0;
683 if (word_digits == 0)
684 /* Two escapes followed by a non-decimal
685 * digit or a decimal digit that would
686 * create a word sequence greater than
687 * 6XXXX, and we're not in the middle of
688 * a word sequence: control character
689 * sequence mode. Interpret the control
690 * sequence and save the corresponding
691 * control character as the result. */
692 retval = get_control_kbinput(kbinput->key);
693 else {
694 /* If we're in the middle of a word
695 * sequence, reset the word sequence
696 * counter and save the character we got
697 * as the result. */
698 word_digits = 0;
699 retval = kbinput->key;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000700 }
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000701 }
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000702 break;
703 }
704 }
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000705
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000706 /* If we have a result and it's an extended keypad value, set
707 * func_key to TRUE. */
708 if (retval != ERR)
709 *func_key = !is_byte_char(retval);
710 } else
711 /* If we didn't get an extended keypad value or an ASCII
712 * character, leave it as-is. */
713 retval = kbinput->key;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000714
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000715#ifdef DEBUG
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000716 fprintf(stderr, "parse_kbinput(): kbinput->key = %d, meta_key = %d, func_key = %d, escapes = %d, word_digits = %d, retval = %d\n", kbinput->key, (int)*meta_key, (int)*func_key, escapes, word_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000717#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000718
719 /* Return the result. */
720 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000721}
722
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000723/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000724 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000725 * are generated when the keypad doesn't support the needed keys. If
726 * the escape sequence is recognized but we want to ignore it, return
727 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
728 * set ignore_seq to FALSE. Assume that Escape has already been read
729 * in. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000730int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000731 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000732{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000733 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000734
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000735 *ignore_seq = FALSE;
736
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000737 if (seq_len > 1) {
738 switch (sequence[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000739 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000740 switch (sequence[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000741 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000742 if (seq_len >= 3) {
743 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000744 case 'P': /* Esc O 2 P == F13 on
745 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000746 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000747 break;
748 case 'Q': /* Esc O 2 Q == F14 on
749 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000750 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000751 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000752 case 'R': /* Esc O 2 R == F15 on
753 * xterm. */
754 retval = KEY_F(15);
755 break;
756 case 'S': /* Esc O 2 S == F16 on
757 * xterm. */
758 retval = KEY_F(16);
759 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000760 }
761 }
762 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000763 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
764 case 'B': /* Esc O B == Down on
765 * VT100/VT320/xterm. */
766 case 'C': /* Esc O C == Right on
767 * VT100/VT320/xterm. */
768 case 'D': /* Esc O D == Left on
769 * VT100/VT320/xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000770 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000771 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000772 case 'E': /* Esc O E == Center (5) on numeric keypad
773 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000774 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000775 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000776 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000777 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000778 break;
779 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000780 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000781 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000782 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000783 * NumLock off on VT100/VT220/VT320/xterm/
784 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000785 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000786 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000787 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000788 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000789 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000790 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000791 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000792 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000793 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000794 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000795 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000796 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000797 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000798 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000799 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000800 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000801 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000802 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000803 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000804 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000805 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000806 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000807 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000808 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000809 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000810 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000811 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000812 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000813 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000814 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000815 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000816 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000817 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000818 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000819 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000820 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000821 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000822 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000823 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000824 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000825 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000826 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000827 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000828 * NumLock off on VT100/VT220/VT320/xterm/
829 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000830 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000831 break;
832 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000833 * NumLock off on VT100/VT220/VT320/xterm/
834 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000835 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000836 break;
837 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000838 * NumLock off on VT100/VT220/VT320/xterm/
839 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000840 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000841 break;
842 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000843 * NumLock off on VT100/VT220/VT320/xterm/
844 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000845 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000846 break;
847 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000848 * with NumLock off on VT100/VT220/VT320/
849 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000850 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000851 break;
852 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000853 * NumLock off on VT100/VT220/VT320/xterm/
854 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000855 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000856 break;
857 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000858 * with NumLock off on VT100/VT220/VT320/
859 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000860 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000861 break;
862 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000863 * with NumLock off on VT100/VT220/VT320/
864 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000865 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000866 break;
867 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000868 * with NumLock off on VT100/VT220/VT320/
869 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000870 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000871 break;
872 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000873 * keypad with NumLock off on VT100/VT220/
874 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000875 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000876 break;
877 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000878 * with NumLock off on VT100/VT220/VT320/
879 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000880 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000881 break;
882 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000883 * with NumLock off on VT100/VT220/VT320/
884 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000885 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000886 break;
887 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000888 * with NumLock off on VT100/VT220/VT320/
889 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000890 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000891 break;
892 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000893 * with NumLock off on VT100/VT220/VT320/
894 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000895 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000896 break;
897 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000898 * with NumLock off on VT100/VT220/VT320/
899 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000900 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000901 break;
902 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000903 * with NumLock off on VT100/VT220/VT320/
904 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000905 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000906 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000907 }
908 break;
909 case 'o':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000910 switch (sequence[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000911 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000912 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000913 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000914 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000915 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000916 break;
917 }
918 break;
919 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000920 switch (sequence[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000921 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000922 if (seq_len >= 3) {
923 switch (sequence[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000924 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
925 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000926 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000927 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000928 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
929 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000930 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000931 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000932 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
933 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000934 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000935 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000936 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
937 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000938 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000939 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000940 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
941 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000942 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000943 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000944 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000945 * VT220/VT320/Linux console/
946 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000947 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000948 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000949 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000950 * VT220/VT320/Linux console/
951 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000952 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000953 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000954 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000955 * VT220/VT320/Linux console/
956 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000957 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000958 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000959 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000960 if (seq_len >= 4) {
961 switch (sequence[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000962 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000963 if (seq_len >= 5) {
964 switch (sequence[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000965 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
966 * xterm. */
967 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
968 * xterm. */
969 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
970 * xterm. */
971 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
972 * xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000973 retval = get_escape_seq_abcd(sequence[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000974 break;
975 }
976 }
977 break;
978 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000979 if (seq_len >= 5) {
980 switch (sequence[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000981 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
982 * xterm. */
983 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
984 * xterm. */
985 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
986 * xterm. */
987 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
988 * xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000989 retval = get_escape_seq_abcd(sequence[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000990 break;
991 }
992 }
993 break;
994 }
995 }
996 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000997 default: /* Esc [ 1 ~ == Home on
998 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000999 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001000 break;
1001 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001002 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001003 break;
1004 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001005 if (seq_len >= 3) {
1006 switch (sequence[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001007 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001008 * VT220/VT320/Linux console/
1009 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001010 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001011 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001012 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001013 * VT220/VT320/Linux console/
1014 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001015 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001016 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001017 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001018 * VT220/VT320/Linux console/
1019 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001020 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001021 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001022 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001023 * VT220/VT320/Linux console/
1024 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001025 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001026 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001027 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001028 * VT220/VT320/Linux console/
1029 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001030 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001031 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001032 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001033 * VT220/VT320/Linux console/
1034 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001035 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001036 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +00001037 case '8': /* Esc [ 2 8 ~ == F15 on
1038 * VT220/VT320/Linux console/
1039 * rxvt/Eterm. */
1040 retval = KEY_F(15);
1041 break;
1042 case '9': /* Esc [ 2 9 ~ == F16 on
1043 * VT220/VT320/Linux console/
1044 * rxvt/Eterm. */
1045 retval = KEY_F(16);
1046 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001047 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001048 * VT220/VT320/Linux console/
1049 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001050 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001051 break;
1052 }
1053 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001054 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001055 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
1056 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001057 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001058 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001059 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001060 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001062 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001063 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
1064 * Linux console/xterm; Esc [ 5 ^ ==
1065 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001066 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001067 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001068 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
1069 * Linux console/xterm; Esc [ 6 ^ ==
1070 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001071 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001072 break;
1073 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001074 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001075 break;
1076 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001077 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001078 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001079 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001080 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001081 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001082 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001083 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001084 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001085 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001086 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001087 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001088 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001089 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001090 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001091 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001092 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001093 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001094 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001095 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001096 * rxvt/Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001097 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001098 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001099 case 'E': /* Esc [ E == Center (5) on numeric keypad
1100 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +00001101 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001102 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001103 case 'F': /* Esc [ F == End on FreeBSD
1104 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001105 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001106 break;
1107 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001108 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001109 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001110 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001111 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001112 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001113 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001114 break;
1115 case 'I': /* Esc [ I == PageUp on FreeBSD
1116 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001117 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001118 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001119 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001120 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001121 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001122 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001123 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001124 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001125 break;
1126 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001127 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001128 break;
1129 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001130 if (seq_len >= 3) {
1131 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001132 case 'P': /* Esc [ O P == F1 on
1133 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001134 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001135 break;
1136 case 'Q': /* Esc [ O Q == F2 on
1137 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001138 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001139 break;
1140 case 'R': /* Esc [ O R == F3 on
1141 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001142 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001143 break;
1144 case 'S': /* Esc [ O S == F4 on
1145 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001146 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001147 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001148 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001149 } else {
1150 /* Esc [ O == F3 on FreeBSD console. */
1151 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001152 }
1153 break;
1154 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001155 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001156 break;
1157 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001158 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001159 break;
1160 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001161 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001162 break;
1163 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001164 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001165 break;
1166 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001167 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001168 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001169 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001170 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001171 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001172 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001173 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001174 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001175 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001176 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001177 break;
1178 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001179 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001180 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001181 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001182 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001183 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001184 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001185 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001186 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001187 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001188 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001189 case 'c': /* Esc [ c == Shift-Right on rxvt/
1190 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001191 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001192 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001193 break;
1194 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001195 if (seq_len >= 3) {
1196 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001197 case 'A': /* Esc [ [ A == F1 on Linux
1198 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001199 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001200 break;
1201 case 'B': /* Esc [ [ B == F2 on Linux
1202 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001203 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001204 break;
1205 case 'C': /* Esc [ [ C == F3 on Linux
1206 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001207 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001208 break;
1209 case 'D': /* Esc [ [ D == F4 on Linux
1210 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001211 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001212 break;
1213 case 'E': /* Esc [ [ E == F5 on Linux
1214 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001215 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001216 break;
1217 }
1218 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001219 break;
1220 }
1221 break;
1222 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001223 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001224
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001225#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001226 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001227#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001228
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001229 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001230}
1231
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001232/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001233 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001234 * to many escape sequences. */
1235int get_escape_seq_abcd(int kbinput)
1236{
1237 switch (tolower(kbinput)) {
1238 case 'a':
1239 return NANO_PREVLINE_KEY;
1240 case 'b':
1241 return NANO_NEXTLINE_KEY;
1242 case 'c':
1243 return NANO_FORWARD_KEY;
1244 case 'd':
1245 return NANO_BACK_KEY;
1246 default:
1247 return ERR;
1248 }
1249}
1250
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001251/* Translate a word sequence: turn a five-digit decimal number from
1252 * 00000 to 65535 into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001253int get_word_kbinput(int kbinput
1254#ifndef NANO_SMALL
1255 , bool reset
1256#endif
1257 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001258{
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001259 static int word_digits = 0, word_kbinput = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001260 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001261
1262#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001263 if (reset) {
1264 word_digits = 0;
1265 word_kbinput = 0;
1266 return ERR;
1267 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001268#endif
1269
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001270 /* Increment the word digit counter. */
1271 word_digits++;
1272
1273 switch (word_digits) {
1274 case 1:
1275 /* One digit: reset the word sequence holder and add the
1276 * digit we got to the 10000's position of the word sequence
1277 * holder. */
1278 word_kbinput = 0;
1279 if ('0' <= kbinput && kbinput <= '6')
1280 word_kbinput += (kbinput - '0') * 10000;
1281 else
1282 /* If the character we got isn't a decimal digit, or if
1283 * it is and it would put the word sequence out of word
1284 * range, save it as the result. */
1285 retval = kbinput;
1286 break;
1287 case 2:
1288 /* Two digits: add the digit we got to the 1000's position
1289 * of the word sequence holder. */
1290 if (('0' <= kbinput && kbinput <= '5') ||
1291 (word_kbinput < 60000 && '6' <= kbinput &&
1292 kbinput <= '9'))
1293 word_kbinput += (kbinput - '0') * 1000;
1294 else
1295 /* If the character we got isn't a decimal digit, or if
1296 * it is and it would put the word sequence out of word
1297 * range, save it as the result. */
1298 retval = kbinput;
1299 break;
1300 case 3:
1301 /* Three digits: add the digit we got to the 100's position
1302 * of the word sequence holder. */
1303 if (('0' <= kbinput && kbinput <= '5') ||
1304 (word_kbinput < 65000 && '6' <= kbinput &&
1305 kbinput <= '9'))
1306 word_kbinput += (kbinput - '0') * 100;
1307 else
1308 /* If the character we got isn't a decimal digit, or if
1309 * it is and it would put the word sequence out of word
1310 * range, save it as the result. */
1311 retval = kbinput;
1312 break;
1313 case 4:
1314 /* Four digits: add the digit we got to the 10's position of
1315 * the word sequence holder. */
1316 if (('0' <= kbinput && kbinput <= '3') ||
1317 (word_kbinput < 65500 && '4' <= kbinput &&
1318 kbinput <= '9'))
1319 word_kbinput += (kbinput - '0') * 10;
1320 else
1321 /* If the character we got isn't a decimal digit, or if
1322 * it is and it would put the word sequence out of word
1323 * range, save it as the result. */
1324 retval = kbinput;
1325 break;
1326 case 5:
1327 /* Five digits: add the digit we got to the 1's position of
1328 * the word sequence holder, and save the corresponding word
1329 * value as the result. */
1330 if (('0' <= kbinput && kbinput <= '5') ||
1331 (word_kbinput < 65530 && '6' <= kbinput &&
1332 kbinput <= '9')) {
1333 word_kbinput += (kbinput - '0');
1334 retval = word_kbinput;
1335 } else
1336 /* If the character we got isn't a decimal digit, or if
1337 * it is and it would put the word sequence out of word
1338 * range, save it as the result. */
1339 retval = kbinput;
1340 break;
1341 default:
1342 /* More than three digits: save the character we got as the
1343 * result. */
1344 retval = kbinput;
1345 break;
1346 }
1347
1348 /* If we have a result, reset the word digit counter and the word
1349 * sequence holder. */
1350 if (retval != ERR) {
1351 word_digits = 0;
1352 word_kbinput = 0;
1353 }
1354
1355#ifdef DEBUG
1356 fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word_kbinput = %d, retval = %d\n", kbinput, word_digits, word_kbinput, retval);
1357#endif
1358
1359 return retval;
1360}
1361
1362/* Translate a control character sequence: turn an ASCII non-control
1363 * character into its corresponding control character. */
1364int get_control_kbinput(int kbinput)
1365{
1366 int retval;
1367
1368 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1369 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1370 kbinput == '`')
1371 retval = NANO_CONTROL_SPACE;
1372 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1373 else if ('3' <= kbinput && kbinput <= '7')
1374 retval = kbinput - 24;
1375 /* Ctrl-8 (Ctrl-?) */
1376 else if (kbinput == '8' || kbinput == '?')
1377 retval = NANO_CONTROL_8;
1378 /* Ctrl-A to Ctrl-_ */
1379 else if ('A' <= kbinput && kbinput <= '_')
1380 retval = kbinput - 64;
1381 /* Ctrl-a to Ctrl-~ */
1382 else if ('a' <= kbinput && kbinput <= '~')
1383 retval = kbinput - 96;
1384 else
1385 retval = kbinput;
1386
1387#ifdef DEBUG
1388 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1389#endif
1390
1391 return retval;
1392}
1393
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001394/* Put the output-formatted key values in the input buffer kbinput back
1395 * into the default keystroke buffer, starting at position pos, so that
1396 * they can be parsed again. */
1397void unparse_kbinput(size_t pos, int *kbinput, size_t kbinput_len)
1398{
1399 if (pos < kbinput_len - 1) {
1400 size_t seq_len = kbinput_len - (kbinput_len - pos);
1401 buffer *sequence = keys_to_buffer(&kbinput[pos + 1],
1402 seq_len);
1403
1404 unget_input(sequence, seq_len);
1405 free(sequence);
1406 }
1407}
1408
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001409/* Read in a string of characters verbatim, and return the length of the
1410 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1411int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1412{
1413 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001414
1415 /* Turn off flow control characters if necessary so that we can type
1416 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001417 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001418 if (ISSET(PRESERVE))
1419 disable_flow_control();
1420 keypad(win, FALSE);
1421
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001422 /* Read in a stream of characters and interpret it if possible. */
1423 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001424
1425 /* Turn flow control characters back on if necessary and turn the
1426 * keypad back on now that we're done. */
1427 if (ISSET(PRESERVE))
1428 enable_flow_control();
1429 keypad(win, TRUE);
1430
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001431 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001432}
1433
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001434/* Read in a stream of all available characters. Translate the first
1435 * few characters of the input into the corresponding word value if
1436 * possible. After that, leave the input as-is. */
1437int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001438{
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001439 buffer *kbinput, *sequence;
1440 int word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001441
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001442 /* Read in the first keystroke. */
1443 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001444
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001445 /* Check whether the first keystroke is a decimal digit. */
1446 word = get_word_kbinput(kbinput->key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001447#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001448 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001449#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001450 );
1451
1452 /* If the first keystroke isn't a decimal digit, put back the first
1453 * keystroke. */
1454 if (word != ERR)
1455 unget_input(kbinput, 1);
1456 /* Otherwise, read in keystrokes until we have a complete word
1457 * sequence, and put back the corresponding word value. */
1458 else {
1459 buffer word_kbinput;
1460
1461 while (word == ERR) {
1462 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001463
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001464 word = get_word_kbinput(kbinput->key
1465#ifndef NANO_SMALL
1466 , FALSE
1467#endif
1468 );
1469 }
1470
1471 word_kbinput.key = word;
1472 word_kbinput.key_code = FALSE;
1473
1474 unget_input(&word_kbinput, 1);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001475 }
1476
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001477 /* Get the complete sequence, and save the key values in it as the
1478 * result. */
1479 *kbinput_len = get_buffer_len();
1480 sequence = get_input(NULL, *kbinput_len);
1481 retval = buffer_to_keys(sequence, *kbinput_len);
1482 free(sequence);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001483
1484 return retval;
1485}
1486
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001487#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001488/* Check for a mouse event, and if one's taken place, save the
1489 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001490 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1491 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001492 * place on it, figure out which shortcut was clicked and put back the
1493 * equivalent keystroke(s). Return FALSE if no keystrokes were
1494 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001495 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001496bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001497{
1498 MEVENT mevent;
1499
1500 *mouse_x = -1;
1501 *mouse_y = -1;
1502
1503 /* First, get the actual mouse event. */
1504 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001505 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001506
1507 /* Save the screen coordinates where the mouse event took place. */
1508 *mouse_x = mevent.x;
1509 *mouse_y = mevent.y;
1510
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001511 /* If we're allowing shortcuts, the current shortcut list is being
1512 * displayed on the last two lines of the screen, and the mouse
1513 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001514 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001515 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1516 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001517 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001518 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001519 /* The number of shortcuts in the current shortcut list. */
1520 const shortcut *s = currshortcut;
1521 /* The actual shortcut we clicked on, starting at the first
1522 * one in the current shortcut list. */
1523
1524 /* Get the shortcut lists' length. */
1525 if (currshortcut == main_list)
1526 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001527 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001528 currslen = length_of_list(currshortcut);
1529
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001530 /* We don't show any more shortcuts than the main list
1531 * does. */
1532 if (currslen > MAIN_VISIBLE)
1533 currslen = MAIN_VISIBLE;
1534 }
1535
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001536 /* Calculate the width of each shortcut in the list (it's the
1537 * same for all of them). */
1538 if (currslen < 2)
1539 i = COLS / 6;
1540 else
1541 i = COLS / ((currslen / 2) + (currslen % 2));
1542
1543 /* Calculate the y-coordinates relative to the beginning of
1544 * bottomwin, i.e, the bottom three lines of the screen. */
1545 j = *mouse_y - (editwinrows + 3);
1546
1547 /* If we're on the statusbar, beyond the end of the shortcut
1548 * list, or beyond the end of a shortcut on the right side of
1549 * the screen, don't do anything. */
1550 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001551 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001552 j = (*mouse_x / i) * 2 + j;
1553 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001554 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001555
1556 /* Go through the shortcut list to determine which shortcut was
1557 * clicked. */
1558 for (; j > 0; j--)
1559 s = s->next;
1560
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001561 /* And put back the equivalent key. Assume that each shortcut
1562 * has, at the very least, an equivalent control key, an
1563 * equivalent primary meta key sequence, or both. */
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001564 if (s->ctrlval != NANO_NO_KEY)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001565 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001566 else if (s->metaval != NANO_NO_KEY)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001567 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001568
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001569 return TRUE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001570 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001571 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001572}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001573#endif /* !DISABLE_MOUSE */
1574
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001575const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001576 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001577{
1578 const shortcut *s = s_list;
1579 size_t slen = length_of_list(s_list);
1580
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001581#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001582 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 +00001583#endif
1584
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001585 /* Check for shortcuts. */
1586 for (; slen > 0; slen--) {
1587 /* We've found a shortcut if:
1588 *
1589 * 1. The key exists.
1590 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001591 * 3. meta_key is TRUE and the key is the primary or
1592 * miscellaneous meta sequence in the shortcut list.
1593 * 4. func_key is TRUE and the key is a function key in the
1594 * shortcut list. */
1595
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001596 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1597 (*meta_key == TRUE && (*kbinput == s->metaval ||
1598 *kbinput == s->miscval)) || (*func_key == TRUE &&
1599 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001600 break;
1601 }
1602
1603 s = s->next;
1604 }
1605
1606 /* Translate the shortcut to either its control key or its meta key
1607 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001608 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001609 if (slen > 0) {
1610 if (s->ctrlval != NANO_NO_KEY) {
1611 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001612 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001613 *kbinput = s->ctrlval;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001614 } else if (s->metaval != NANO_NO_KEY) {
1615 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001616 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001617 *kbinput = s->metaval;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001618 }
1619 return s;
1620 }
1621
1622 return NULL;
1623}
1624
1625#ifndef NANO_SMALL
1626const toggle *get_toggle(int kbinput, bool meta_key)
1627{
1628 const toggle *t = toggles;
1629
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001630#ifdef DEBUG
1631 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1632#endif
1633
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001634 /* Check for toggles. */
1635 for (; t != NULL; t = t->next) {
1636 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001637 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001638 if (meta_key && kbinput == t->val)
1639 break;
1640 }
1641
1642 return t;
1643}
1644#endif /* !NANO_SMALL */
1645
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001646int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
1647 bool *finished, bool allow_funcs)
1648{
1649 int input;
1650 /* The character we read in. */
1651 static int *kbinput = NULL;
1652 /* The input buffer. */
1653 static size_t kbinput_len = 0;
1654 /* The length of the input buffer. */
1655 const shortcut *s;
1656 bool have_shortcut;
1657
1658 *s_or_t = FALSE;
1659 *finished = FALSE;
1660
1661 /* Read in a character. */
1662 input = get_kbinput(bottomwin, meta_key, func_key);
1663
1664#ifndef DISABLE_MOUSE
1665 /* If we got a mouse click and it was on a shortcut, read in the
1666 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001667 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001668 if (do_mouse())
1669 input = get_kbinput(bottomwin, meta_key, func_key);
1670 else
1671 input = ERR;
1672 }
1673#endif
1674
1675 /* Check for a shortcut in the current list. */
1676 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1677
1678 /* If we got a shortcut from the current list, or a "universal"
1679 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1680 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1681 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1682 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1683 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001684 input == NANO_CUT_KEY || (*meta_key == TRUE &&
1685 input == NANO_VERBATIM_KEY));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001686
1687 /* Set s_or_t to TRUE if we got a shortcut. */
1688 *s_or_t = have_shortcut;
1689
1690 if (allow_funcs) {
1691 if (input != ERR && *s_or_t == FALSE && !is_cntrl_char(input)) {
1692 /* If we're using restricted mode, the filename isn't blank,
1693 * and we're at the "Write File" prompt, disable text
1694 * input. */
1695 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1696 currshortcut != writefile_list) {
1697 kbinput_len++;
1698 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1699 sizeof(int));
1700 kbinput[kbinput_len - 1] = input;
1701 }
1702 }
1703
1704 /* If we got a shortcut, or if there aren't any other characters
1705 * waiting after the one we read in, we need to display all the
1706 * characters in the input buffer if it isn't empty. */
1707 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1708 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001709 bool got_enter;
1710 /* Whether we got the Enter key. */
1711
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001712 /* Display all the characters in the input buffer at
1713 * once. */
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001714 do_statusbar_output(kbinput, kbinput_len, &got_enter);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001715
1716 /* Empty the input buffer. */
1717 kbinput_len = 0;
1718 free(kbinput);
1719 kbinput = NULL;
1720 }
1721 }
1722
1723 if (have_shortcut) {
1724 switch (input) {
1725 /* Handle the "universal" statusbar prompt shortcuts. */
1726 case NANO_REFRESH_KEY:
1727 total_refresh();
1728 break;
1729 case NANO_HOME_KEY:
1730 do_statusbar_home();
1731 break;
1732 case NANO_END_KEY:
1733 do_statusbar_end();
1734 break;
1735 case NANO_FORWARD_KEY:
1736 do_statusbar_right();
1737 break;
1738 case NANO_BACK_KEY:
1739 do_statusbar_left();
1740 break;
1741 case NANO_BACKSPACE_KEY:
1742 /* If we're using restricted mode, the filename
1743 * isn't blank, and we're at the "Write File"
1744 * prompt, disable Backspace. */
1745 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1746 currshortcut != writefile_list)
1747 do_statusbar_backspace();
1748 break;
1749 case NANO_DELETE_KEY:
1750 /* If we're using restricted mode, the filename
1751 * isn't blank, and we're at the "Write File"
1752 * prompt, disable Delete. */
1753 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1754 currshortcut != writefile_list)
1755 do_statusbar_delete();
1756 break;
1757 case NANO_CUT_KEY:
1758 /* If we're using restricted mode, the filename
1759 * isn't blank, and we're at the "Write File"
1760 * prompt, disable Cut. */
1761 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1762 currshortcut != writefile_list)
1763 do_statusbar_cut_text();
1764 break;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001765 case NANO_VERBATIM_KEY:
1766 if (*meta_key == TRUE) {
1767 /* If we're using restricted mode, the filename
1768 * isn't blank, and we're at the "Write File"
1769 * prompt, disable verbatim input. */
1770 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001771 currshortcut != writefile_list) {
1772 bool got_enter;
1773 /* Whether we got the Enter key. */
1774
1775 do_statusbar_verbatim_input(&got_enter);
1776
1777 /* If we got the Enter key, set finished to
1778 * TRUE to indicate that we're done. */
1779 if (got_enter)
1780 *finished = TRUE;
1781 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001782 break;
1783 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001784 /* Handle the normal statusbar prompt shortcuts, setting
1785 * finished to TRUE to indicate that we're done after
1786 * running or trying to run their associated
1787 * functions. */
1788 default:
1789 if (s->func != NULL) {
1790 if (ISSET(VIEW_MODE) && !s->viewok)
1791 print_view_warning();
1792 else
1793 s->func();
1794 }
1795 *finished = TRUE;
1796 }
1797 }
1798 }
1799
1800 return input;
1801}
1802
1803#ifndef DISABLE_MOUSE
1804bool do_statusbar_mouse(void)
1805{
1806 /* FIXME: If we clicked on a location in the statusbar, the cursor
1807 * should move to the location we clicked on. This functionality
1808 * should be in this function. */
1809 int mouse_x, mouse_y;
1810 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1811}
1812#endif
1813
1814void do_statusbar_home(void)
1815{
1816#ifndef NANO_SMALL
1817 if (ISSET(SMART_HOME)) {
1818 size_t statusbar_x_save = statusbar_x;
1819 for (statusbar_x = 0; isblank(answer[statusbar_x]) &&
1820 statusbar_x < statusbar_xend; statusbar_x++)
1821 ;
1822 if (statusbar_x == statusbar_x_save ||
1823 statusbar_x == statusbar_xend)
1824 statusbar_x = 0;
1825 } else
1826#endif
1827 statusbar_x = 0;
1828}
1829
1830void do_statusbar_end(void)
1831{
1832 statusbar_x = statusbar_xend;
1833}
1834
1835void do_statusbar_right(void)
1836{
1837 if (statusbar_x < statusbar_xend)
1838 statusbar_x = move_right(answer, statusbar_x);
1839}
1840
1841void do_statusbar_left(void)
1842{
1843 if (statusbar_x > 0)
1844 statusbar_x = move_left(answer, statusbar_x);
1845}
1846
1847void do_statusbar_backspace(void)
1848{
1849 if (statusbar_x > 0) {
1850 do_statusbar_left();
1851 do_statusbar_delete();
1852 }
1853}
1854
1855void do_statusbar_delete(void)
1856{
1857 if (statusbar_x < statusbar_xend) {
1858 int char_len = parse_char(answer + statusbar_x, NULL, NULL
1859#ifdef NANO_WIDE
1860 , NULL
1861#endif
1862 );
1863
1864 charmove(answer + statusbar_x, answer + statusbar_x + char_len,
1865 statusbar_xend - statusbar_x - char_len + 1);
1866 statusbar_xend -= char_len;
1867 }
1868}
1869
1870void do_statusbar_cut_text(void)
1871{
1872 null_at(&answer, 0);
1873 statusbar_x = 0;
1874 statusbar_xend = 0;
1875}
1876
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001877void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001878{
1879 int *kbinput; /* Used to hold verbatim input. */
1880 size_t kbinput_len; /* Length of verbatim input. */
1881
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001882 *got_enter = FALSE;
1883
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001884 /* Read in all the verbatim characters. */
1885 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
1886
1887 /* Display all the verbatim characters at once. */
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001888 do_statusbar_output(kbinput, kbinput_len, got_enter);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001889
1890 free(kbinput);
1891}
1892
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001893void do_statusbar_output(int *kbinput, size_t kbinput_len, bool
1894 *got_enter)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001895{
1896 size_t i;
1897
1898 char *key =
1899#ifdef NANO_WIDE
1900 !ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
1901#endif
1902 charalloc(1);
1903
1904 assert(answer != NULL);
1905
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001906 *got_enter = FALSE;
1907
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001908 for (i = 0; i < kbinput_len; i++) {
1909 int key_len;
1910
1911 /* Null to newline, if needed. */
1912 if (kbinput[i] == '\0')
1913 kbinput[i] = '\n';
1914 /* Newline to Enter, if needed. */
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001915 else if (kbinput[i] == '\n') {
1916 /* Set got_enter to TRUE to indicate that we got the Enter
1917 * key, put back the rest of the keystrokes in kbinput so
1918 * that they can be parsed again, and get out. */
1919 *got_enter = TRUE;
1920 unparse_kbinput(i, kbinput, kbinput_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001921 return;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001922 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001923
1924#ifdef NANO_WIDE
1925 /* Change the wide character to its multibyte value. If it's
1926 * invalid, go on to the next character. */
1927 if (!ISSET(NO_UTF8)) {
1928 key_len = wctomb(key, (wchar_t)kbinput[i]);
1929
1930 if (key_len == -1)
1931 continue;
1932 /* Interpret the character as a single-byte sequence. */
1933 } else {
1934#endif
1935 key_len = 1;
1936 key[0] = (unsigned char)kbinput[i];
1937#ifdef NANO_WIDE
1938 }
1939#endif
1940
1941 /* More dangerousness fun =) */
1942 answer = charealloc(answer, statusbar_xend + key_len + 1);
1943
1944 assert(statusbar_x <= statusbar_xend);
1945
1946 charmove(&answer[statusbar_x + key_len], &answer[statusbar_x],
1947 statusbar_xend - statusbar_x + key_len);
1948 charcpy(&answer[statusbar_x], key, key_len);
1949 statusbar_xend += key_len;
1950
1951 do_statusbar_right();
1952 }
1953
1954 free(key);
1955}
1956
Chris Allegretta6df90f52002-07-19 01:08:59 +00001957/* Return the placewewant associated with current_x. That is, xplustabs
1958 * is the zero-based column position of the cursor. Value is no smaller
1959 * than current_x. */
1960size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001961{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001962 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001963}
1964
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001965/* actual_x() gives the index in str of the character displayed at
1966 * column xplus. That is, actual_x() is the largest value such that
1967 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
1968size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001969{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001970 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00001971 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001972 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00001973 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001974
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001975 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001976
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001977 while (*str != '\0') {
1978 int str_len = parse_char(str, NULL, &length
1979#ifdef NANO_WIDE
1980 , NULL
1981#endif
1982 );
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001983
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001984 if (length > xplus)
1985 break;
1986
1987 i += str_len;
1988 str += str_len;
1989 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001990
Chris Allegretta6df90f52002-07-19 01:08:59 +00001991 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00001992}
1993
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00001994/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001995 * columns wide are the first size characters of str? */
1996size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00001997{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001998 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001999 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002000
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002001 if (size == 0)
2002 return 0;
2003
2004 assert(str != NULL);
2005
2006 while (*str != '\0') {
2007 int str_len = parse_char(str, NULL, &length
2008#ifdef NANO_WIDE
2009 , NULL
2010#endif
2011 );
2012
2013 str += str_len;
2014
2015 if (size <= str_len)
2016 break;
2017
2018 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002019 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002020
Chris Allegretta6df90f52002-07-19 01:08:59 +00002021 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002022}
2023
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002024/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002025size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002026{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002027 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002028}
2029
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002030void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002031{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002032 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002033}
2034
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002035void blank_edit(void)
2036{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002037 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002038 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002039 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002040}
2041
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002042void blank_statusbar(void)
2043{
2044 mvwaddstr(bottomwin, 0, 0, hblank);
2045}
2046
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002047void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002048{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002049 if (statusblank > 1)
2050 statusblank--;
2051 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
2052 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002053 blank_statusbar();
2054 wnoutrefresh(bottomwin);
2055 reset_cursor();
2056 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002057 }
2058}
2059
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002060void blank_bottombars(void)
2061{
2062 if (!ISSET(NO_HELP)) {
2063 mvwaddstr(bottomwin, 1, 0, hblank);
2064 mvwaddstr(bottomwin, 2, 0, hblank);
2065 }
2066}
2067
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002068/* buf is a multibyte string to be displayed. We need to expand tabs
2069 * and control characters. How many bytes do we need to display?
2070 * start_col is the column of *buf (usually 0). We display to
2071 * (end_col - 1). */
2072size_t display_string_len(const char *buf, size_t start_col, size_t
2073 end_col)
2074{
2075 size_t retval = 0;
2076
2077 assert(buf != NULL);
2078
2079 /* Throughout the loop, we maintain the fact that *buf displays at
2080 * column start_col. */
2081 while (start_col <= end_col && *buf != '\0') {
2082 int wide_buf, wide_buf_len;
2083 size_t old_col = start_col;
2084#ifdef NANO_WIDE
2085 bool bad_char;
2086#endif
2087
2088 wide_buf_len = parse_char(buf, &wide_buf, &start_col
2089#ifdef NANO_WIDE
2090 , &bad_char
2091#endif
2092 );
2093
2094#ifdef NANO_WIDE
2095 /* If buf contains a null byte or an invalid multibyte
2096 * character, interpret that character as though it's a wide
2097 * character. */
2098 if (!ISSET(NO_UTF8) && bad_char) {
2099 char *bad_wide_buf = charalloc(MB_CUR_MAX);
2100 int bad_wide_buf_len;
2101
2102 /* If we have a control character, add one byte to account
2103 * for the "^" that will be displayed in front of it, and
2104 * translate the character to its visible equivalent as
2105 * returned by control_rep(). */
2106 if (is_cntrl_char(wide_buf)) {
2107 retval++;
2108 wide_buf = control_rep((unsigned char)wide_buf);
2109 }
2110
2111 /* Translate the wide character to its multibyte
2112 * equivalent. */
2113 bad_wide_buf_len = wctomb(bad_wide_buf, (wchar_t)wide_buf);
2114
2115 if (bad_wide_buf_len != -1)
2116 retval += bad_wide_buf_len;
David Lawrence Ramseyf2824282004-12-29 21:32:22 +00002117 else
2118 retval++;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002119
2120 free(bad_wide_buf);
2121 } else {
2122#endif
2123 /* If we have a tab, get its width in bytes using the
2124 * current value of col. */
2125 if (wide_buf == '\t')
2126 retval += start_col - old_col;
2127 /* If we have a control character, add one byte to account
2128 * for the "^" that will be displayed in front of it, and
2129 * then add the number of bytes for its visible equivalent
2130 * as returned by control_rep(). If we have an invalid
2131 * multibyte control character, interpret that character as
2132 * though it's a normal control character. */
2133 else if (is_cntrl_char(wide_buf)) {
2134 char ctrl_wide_buf =
2135 control_rep((unsigned char)wide_buf);
2136
2137 retval++;
2138 retval += parse_char(&ctrl_wide_buf, NULL, NULL
2139#ifdef NANO_WIDE
2140 , NULL
2141#endif
2142 );
2143 /* If we have a normal character, add its width in bytes
2144 * normally. */
2145 } else
2146#ifdef NANO_WIDE
2147 /* If buf contains an invalid multibyte non-control
2148 * character, interpret that character as though it's a
2149 * normal non-control character. */
2150 if (!ISSET(NO_UTF8) && bad_char) {
2151 char *bad_wide_buf = charalloc(MB_CUR_MAX);
2152 int bad_wide_buf_len;
2153
2154 bad_wide_buf_len = wctomb(bad_wide_buf,
2155 (wchar_t)wide_buf);
2156
2157 free(bad_wide_buf);
2158
David Lawrence Ramseyf2824282004-12-29 21:32:22 +00002159 if (bad_wide_buf_len != -1)
2160 retval += bad_wide_buf_len;
2161 else
2162 retval++;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002163 } else
2164#endif
2165 retval += wide_buf_len;
2166#ifdef NANO_WIDE
2167 }
2168
2169 buf += wide_buf_len;
2170#endif
2171 }
2172
2173 return retval;
2174}
2175
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002176/* Convert buf into a string that can be displayed on screen. The
2177 * caller wants to display buf starting with column start_col, and
2178 * extending for at most len columns. start_col is zero-based. len is
2179 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002180 * string is dynamically allocated, and should be freed. If dollars is
2181 * TRUE, the caller might put "$" at the beginning or end of the line if
2182 * it's too long. */
2183char *display_string(const char *buf, size_t start_col, size_t len, bool
2184 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002185{
2186 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002187 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002188 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002189 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002190 size_t alloc_len;
2191 /* The length of memory allocated for converted. */
2192 char *converted;
2193 /* The string we return. */
2194 size_t index;
2195 /* Current position in converted. */
2196
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002197 /* If dollars is TRUE, make room for the "$" at the end of the
2198 * line. Also make sure that we don't try to display only part of a
2199 * multicolumn character there. */
2200 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2201 len--;
2202
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002203 if (len == 0)
2204 return mallocstrcpy(NULL, "");
2205
2206 start_index = actual_x(buf, start_col);
2207 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002208
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002209 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002210
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002211 alloc_len = display_string_len(buf + start_index, start_col,
2212 start_col + COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002213 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002214 index = 0;
2215
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002216 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002217 buf[start_index] != '\t')) {
2218 int wide_buf, wide_buf_len;
2219
2220 /* We don't display all of buf[start_index] since it starts to
2221 * the left of the screen. */
2222 wide_buf_len = parse_char(buf + start_index, &wide_buf, NULL
2223#ifdef NANO_WIDE
2224 , NULL
2225#endif
2226 );
2227
2228 if (is_cntrl_char(wide_buf)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002229 if (column < start_col) {
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002230 char *ctrl_wide_buf =
2231#ifdef NANO_WIDE
2232 !ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
2233#endif
2234 charalloc(1);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002235 int ctrl_wide_buf_len, i;
2236
2237 wide_buf = control_rep((unsigned char)wide_buf);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002238
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002239#ifdef NANO_WIDE
David Lawrence Ramseyf2824282004-12-29 21:32:22 +00002240 if (!ISSET(NO_UTF8)) {
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002241 ctrl_wide_buf_len = wctomb(ctrl_wide_buf,
2242 (wchar_t)wide_buf);
David Lawrence Ramseyf2824282004-12-29 21:32:22 +00002243
2244 if (ctrl_wide_buf_len == -1) {
2245 ctrl_wide_buf_len = 1;
2246 ctrl_wide_buf[0] = ' ';
2247 }
2248 } else {
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002249#endif
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002250 ctrl_wide_buf_len = 1;
2251 ctrl_wide_buf[0] = (unsigned char)wide_buf;
2252#ifdef NANO_WIDE
2253 }
2254#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002255
2256 for (i = 0; i < ctrl_wide_buf_len; i++)
2257 converted[index++] = ctrl_wide_buf[i];
2258
2259 free(ctrl_wide_buf);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002260
2261 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002262 start_index += wide_buf_len;
2263 }
2264 } else if (wcwidth(wide_buf) > 1) {
2265 /* If dollars is TRUE, make room for the "$" at the
2266 * beginning of the line. Also make sure that we don't try
2267 * to display only part of a multicolumn character there. */
2268 converted[0] = ' ';
2269 index = 1;
2270 if (dollars && column == start_col) {
2271 converted[1] = ' ';
2272 index = 2;
2273 }
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002274
2275 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002276 start_index += wide_buf_len;
2277 }
2278 }
2279
2280 while (index < alloc_len && buf[start_index] != '\0') {
2281 int wide_buf, wide_buf_len;
David Lawrence Ramsey9ec76e52004-12-23 19:55:57 +00002282#ifdef NANO_WIDE
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002283 bool bad_char;
David Lawrence Ramsey9ec76e52004-12-23 19:55:57 +00002284#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002285
2286 wide_buf_len = parse_char(buf + start_index, &wide_buf, NULL
2287#ifdef NANO_WIDE
2288 , &bad_char
2289#endif
2290 );
2291
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002292 if (wide_buf == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002293 converted[index++] =
2294#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2295 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
2296#endif
2297 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002298 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002299 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002300 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002301 start_col++;
2302 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002303 /* If buf contains a control character, interpret it. If it
2304 * contains an invalid multibyte control character, interpret
2305 * that character as though it's a normal control character. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002306 } else if (is_cntrl_char(wide_buf)) {
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002307 char *ctrl_wide_buf =
2308#ifdef NANO_WIDE
2309 !ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
2310#endif
2311 charalloc(1);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002312 int ctrl_wide_buf_len, i;
2313
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002314 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002315 start_col++;
2316 wide_buf = control_rep((unsigned char)wide_buf);
2317
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002318#ifdef NANO_WIDE
David Lawrence Ramseyf2824282004-12-29 21:32:22 +00002319 if (!ISSET(NO_UTF8)) {
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002320 ctrl_wide_buf_len = wctomb(ctrl_wide_buf,
2321 (wchar_t)wide_buf);
David Lawrence Ramseyf2824282004-12-29 21:32:22 +00002322
2323 if (ctrl_wide_buf_len == -1) {
2324 ctrl_wide_buf_len = 1;
2325 ctrl_wide_buf[0] = ' ';
2326 }
2327 } else {
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002328#endif
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002329 ctrl_wide_buf_len = 1;
2330 ctrl_wide_buf[0] = (unsigned char)wide_buf;
2331#ifdef NANO_WIDE
2332 }
2333#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002334
2335 for (i = 0; i < ctrl_wide_buf_len; i++)
2336 converted[index++] = ctrl_wide_buf[i];
2337
2338 free(ctrl_wide_buf);
2339
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002340 start_col +=
2341#ifdef NANO_WIDE
2342 !ISSET(NO_UTF8) ? wcwidth((wchar_t)wide_buf) :
2343#endif
2344 1;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002345 } else if (wide_buf == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002346 converted[index++] =
2347#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2348 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
2349#endif
2350 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002351 start_col++;
2352 } else {
2353 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002354
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002355#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002356 /* If buf contains an invalid multibyte non-control
2357 * character, interpret that character as though it's a
2358 * normal non-control character. */
2359 if (!ISSET(NO_UTF8) && bad_char) {
2360 char *bad_wide_buf = charalloc(MB_CUR_MAX);
2361 int bad_wide_buf_len;
2362
2363 bad_wide_buf_len = wctomb(bad_wide_buf,
2364 (wchar_t)wide_buf);
2365
David Lawrence Ramseyf2824282004-12-29 21:32:22 +00002366 if (bad_wide_buf_len == -1) {
2367 bad_wide_buf_len = 1;
2368 bad_wide_buf[0] = ' ';
2369 }
2370
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002371 for (i = 0; i < bad_wide_buf_len; i++)
2372 converted[index++] = bad_wide_buf[i];
2373
2374 free(bad_wide_buf);
2375 } else {
2376#endif
2377 for (i = 0; i < wide_buf_len; i++)
2378 converted[index++] = buf[start_index + i];
2379#ifdef NANO_WIDE
2380 }
2381
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002382 if (!ISSET(NO_UTF8))
2383 start_col += wcwidth((wchar_t)wide_buf);
2384 else
2385#endif
2386 start_col++;
2387 }
2388
2389 start_index += wide_buf_len;
2390 }
2391
2392 /* Make sure that converted is at most len columns wide. */
2393 converted[index] = '\0';
2394 index = actual_x(converted, len);
2395 null_at(&converted, index);
2396
2397 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002398}
2399
Chris Allegretta7662c862003-01-13 01:35:15 +00002400/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002401 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002402 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002403 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002404 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002405void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002406{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002407 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002408 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002409
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002410 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002411
Chris Allegrettab3655b42001-10-22 03:15:31 +00002412 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002413 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002414
Chris Allegretta6df90f52002-07-19 01:08:59 +00002415 mvwaddstr(bottomwin, 0, 0, buf);
2416 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002417
2418 if (COLS > 1)
2419 waddch(bottomwin, x_real < wid ? ' ' : '$');
2420 if (COLS > 2) {
2421 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002422 char *expanded = display_string(inputbuf, page_start, wid,
2423 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002424
2425 assert(wid > 0);
2426 assert(strlen(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002427
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002428 waddstr(bottomwin, expanded);
2429 free(expanded);
2430 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2431 } else
2432 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002433 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002434}
2435
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002436/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002437 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002438int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002439#ifndef NANO_SMALL
2440 historyheadtype *history_list,
2441#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002442 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002443#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002444 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002445#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002446 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002447{
2448 int kbinput;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002449 bool meta_key, func_key, s_or_t, finished;
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002450 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002451 /* used by input_tab() */
Chris Allegretta598106e2002-01-19 01:59:37 +00002452
Chris Allegretta5beed502003-01-05 20:41:21 +00002453#ifndef NANO_SMALL
2454 /* for history */
2455 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00002456 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00002457 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002458 int last_kbinput = 0;
2459
2460 /* This variable is used in the search history code. use_cb == 0
2461 means that we're using the existing history and ignoring
2462 currentbuf. use_cb == 1 means that the entry in answer should be
2463 moved to currentbuf or restored from currentbuf to answer.
2464 use_cb == 2 means that the entry in currentbuf should be moved to
2465 answer or restored from answer to currentbuf. */
2466 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002467#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002468 statusbar_xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002469
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002470 /* Only put statusbar_x at the end of the string if it's
2471 * uninitialized, if it would be past the end of the string as it
2472 * is, or if resetstatuspos is TRUE. Otherwise, leave it alone.
2473 * This is so the cursor position stays at the same place if a
2474 * prompt-changing toggle is pressed. */
2475 if (statusbar_x == (size_t)-1 || statusbar_x > statusbar_xend ||
2476 resetstatuspos)
2477 statusbar_x = statusbar_xend;
Chris Allegretta09fc4302003-01-16 22:16:38 +00002478
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002479 answer = charealloc(answer, statusbar_xend + 1);
2480 if (statusbar_xend > 0)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002481 strcpy(answer, def);
2482 else
2483 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002484
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002485 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002486
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002487 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00002488
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002489 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002490
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002491 /* Refresh the edit window before getting input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002492 wnoutrefresh(edit);
2493 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002494
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002495 /* If we're using restricted mode, we aren't allowed to change the
2496 * name of a file once it has one because that would allow writing
2497 * to files not specified on the command line. In this case,
2498 * disable all keys that would change the text if the filename isn't
2499 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002500 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
2501 &s_or_t, &finished, TRUE)) != NANO_CANCEL_KEY &&
2502 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002503
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002504 /* If we have a shortcut with an associated function, break out
2505 * if we're finished after running the function. */
2506 if (finished)
2507 break;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002508
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002509 assert(statusbar_x <= statusbar_xend &&
2510 statusbar_xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002511
Chris Allegretta04d848e2000-11-05 17:54:41 +00002512 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002513 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00002514
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002515 switch (kbinput) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002516 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002517#ifndef NANO_SMALL
2518 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00002519 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002520 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002521 history_list->current = (historytype *)history_list;
2522 history_list->len = strlen(answer);
2523 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002524
Chris Allegretta7662c862003-01-13 01:35:15 +00002525 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002526 complete = get_history_completion(history_list, answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002527 statusbar_x = strlen(complete);
2528 statusbar_xend = statusbar_x;
Chris Allegretta5beed502003-01-05 20:41:21 +00002529 answer = mallocstrcpy(answer, complete);
2530 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002531 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002532#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002533 else
2534#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002535#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002536#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002537 if (allow_tabs) {
Chris Allegretta327abda2003-01-17 05:04:17 +00002538 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002539
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002540 answer = input_tab(answer, statusbar_x, &tabbed, &shift,
2541 list);
2542 statusbar_xend = strlen(answer);
2543 statusbar_x += shift;
2544 if (statusbar_x > statusbar_xend)
2545 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002546 }
2547#endif
2548 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002549 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002550#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002551 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002552
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002553 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2554 isn't NULL, and currentbuf is different from answer,
2555 it means that we're scrolling up at the top of the
2556 search history, and we need to save the current
2557 answer in currentbuf; do this and reset use_cb to
2558 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002559 if (currentbuf == NULL || (use_cb == 1 &&
2560 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002561 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002562 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002563 }
2564
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002565 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2566 is different from answer, it means that we're
2567 scrolling up at the bottom of the search history, and
2568 we need to make the string in currentbuf the current
2569 answer; do this, blow away currentbuf since we don't
2570 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002571 if (currentbuf != NULL && use_cb == 2 &&
2572 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002573 answer = mallocstrcpy(answer, currentbuf);
2574 free(currentbuf);
2575 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002576 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002577 use_cb = 0;
2578
2579 /* else get older search from the history list and save
2580 it in answer; if there is no older search, blank out
2581 answer */
2582 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002583 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002584 statusbar_xend = strlen(history);
Chris Allegretta5beed502003-01-05 20:41:21 +00002585 } else {
2586 answer = mallocstrcpy(answer, "");
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002587 statusbar_xend = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002588 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002589 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002590 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002591#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002592 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002593 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002594#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002595 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002596
2597 /* get newer search from the history list and save it
2598 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002599 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002600 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002601 statusbar_xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002602
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002603 /* if there is no newer search, we're here */
2604
2605 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2606 that we're scrolling down at the bottom of the search
2607 history and we need to make the string in currentbuf
2608 the current answer; do this, blow away currentbuf
2609 since we don't need it anymore, and set use_cb to
2610 1 */
2611 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002612 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002613 free(currentbuf);
2614 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002615 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002616 use_cb = 1;
2617
2618 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2619 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002620 the search history and the current answer (if it's
2621 not blank) needs to be saved in currentbuf; do this,
2622 blank out answer (if necessary), and set use_cb to
2623 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002624 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002625 if (answer[0] != '\0') {
2626 currentbuf = mallocstrcpy(currentbuf, answer);
2627 answer = mallocstrcpy(answer, "");
2628 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002629 statusbar_xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002630 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002631 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002632 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002633 }
2634#endif
2635 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002636 }
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002637#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002638 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002639#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002640 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002641 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002642 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002643
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002644 /* We finished putting in an answer, so reset statusbar_x. */
2645 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY)
2646 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002647
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002648 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002649}
2650
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002651/* Ask a question on the statusbar. Answer will be stored in answer
2652 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2653 * otherwise, the valid shortcut key caught. def is any editable text
2654 * we want to put up by default.
2655 *
2656 * New arg tabs tells whether or not to allow tab completion. */
2657int statusq(bool allow_tabs, const shortcut *s, const char *def,
2658#ifndef NANO_SMALL
2659 historyheadtype *which_history,
2660#endif
2661 const char *msg, ...)
2662{
2663 va_list ap;
2664 char *foo = charalloc(COLS - 3);
2665 int ret;
2666#ifndef DISABLE_TABCOMP
2667 bool list = FALSE;
2668#endif
2669
2670 bottombars(s);
2671
2672 va_start(ap, msg);
2673 vsnprintf(foo, COLS - 4, msg, ap);
2674 va_end(ap);
2675 foo[COLS - 4] = '\0';
2676
2677 ret = nanogetstr(allow_tabs, foo, def,
2678#ifndef NANO_SMALL
2679 which_history,
2680#endif
2681 s
2682#ifndef DISABLE_TABCOMP
2683 , &list
2684#endif
2685 );
2686 free(foo);
2687 resetstatuspos = FALSE;
2688
2689 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002690 case NANO_CANCEL_KEY:
2691 ret = -1;
2692 resetstatuspos = TRUE;
2693 break;
2694 case NANO_ENTER_KEY:
2695 ret = (answer[0] == '\0') ? -2 : 0;
2696 resetstatuspos = TRUE;
2697 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002698 }
2699 blank_statusbar();
2700
2701#ifdef DEBUG
2702 fprintf(stderr, "I got \"%s\"\n", answer);
2703#endif
2704
2705#ifndef DISABLE_TABCOMP
2706 /* if we've done tab completion, there might be a list of
2707 filename matches on the edit window at this point; make sure
2708 they're cleared off. */
2709 if (list)
2710 edit_refresh();
2711#endif
2712
2713 return ret;
2714}
2715
2716void statusq_abort(void)
2717{
2718 resetstatuspos = TRUE;
2719}
2720
Chris Allegrettaf717f982003-02-13 22:25:01 +00002721void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002722{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002723 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002724 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002725 size_t verlen = strlenpt(VERMSG) + 1;
2726 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002727 const char *prefix;
2728 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2729 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002730 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002731 const char *state;
2732 /* "Modified", "View", or spaces the length of "Modified".
2733 * Tells the state of this buffer. */
2734 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002735 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002736 char *exppath = NULL;
2737 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002738 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002739 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002740 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002741 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002742
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002743 assert(path != NULL || filename != NULL);
2744 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002745
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002746 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002747
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002748 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002749
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002750 if (COLS <= 5 || COLS - 5 < verlen)
2751 space = 0;
2752 else {
2753 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002754 /* Reserve 2/3 of the screen plus one column for after the
2755 * version message. */
2756 if (space < COLS - (COLS / 3) + 1)
2757 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002758 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002759
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002760 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002761 /* The version message should only take up 1/3 of the screen
2762 * minus one column. */
2763 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002764 waddstr(topwin, " ");
2765 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002766
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002767 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002768 state = _("Modified");
2769 else if (path == NULL && ISSET(VIEW_MODE))
2770 state = _("View");
2771 else {
2772 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002773 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002774 state = &hblank[COLS - statelen];
2775 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002776 statelen = strnlenpt(state, COLS);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002777 /* We need a space before state. */
2778 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2779 statelen++;
2780
2781 assert(space >= 0);
2782 if (space == 0 || statelen >= space)
2783 goto the_end;
2784
2785#ifndef DISABLE_BROWSER
2786 if (path != NULL)
2787 prefix = _("DIR:");
2788 else
2789#endif
2790 if (filename[0] == '\0') {
2791 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002792 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002793 } else
2794 prefix = _("File:");
2795 assert(statelen < space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002796 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002797 /* If newfie is FALSE, we need a space after prefix. */
2798 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002799 prefixlen++;
2800
2801 if (path == NULL)
2802 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002803 if (space >= prefixlen + statelen)
2804 space -= prefixlen + statelen;
2805 else
2806 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002807 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002808 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002809 size_t lenpt = strlenpt(path), start_col;
2810
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002811 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002812
2813 if (dots) {
2814 start_col = lenpt - space + 3;
2815 space -= 3;
2816 } else
2817 start_col = 0;
2818
2819 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002820 }
2821
2822 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002823 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2824 /* The length of the expanded filename. */
2825
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002826 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002827 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002828 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002829 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002830 assert(strlenpt(prefix) + 1 == prefixlen);
2831
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002832 waddch(topwin, ' ');
2833 waddstr(topwin, exppath);
2834 }
2835 } else {
2836 /* We will say something like "File: ...ename". */
2837 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002838 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002839 goto the_end;
2840 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002841 waddnstr(topwin, "...", space + 3);
2842 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002843 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002844 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002845 }
2846
2847 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002848 free(exppath);
2849
2850 if (COLS <= 1 || statelen >= COLS - 1)
2851 mvwaddnstr(topwin, 0, 0, state, COLS);
2852 else {
2853 assert(COLS - statelen - 2 >= 0);
2854 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2855 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2856 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002857
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002858 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002859
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002860 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002861 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002862 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002863}
2864
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002865/* If modified is not already set, set it and update titlebar. */
2866void set_modified(void)
2867{
2868 if (!ISSET(MODIFIED)) {
2869 SET(MODIFIED);
2870 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002871 }
2872}
2873
2874void statusbar(const char *msg, ...)
2875{
2876 va_list ap;
2877
2878 va_start(ap, msg);
2879
2880 /* Curses mode is turned off. If we use wmove() now, it will muck
2881 * up the terminal settings. So we just use vfprintf(). */
2882 if (curses_ended) {
2883 vfprintf(stderr, msg, ap);
2884 va_end(ap);
2885 return;
2886 }
2887
2888 /* Blank out the line. */
2889 blank_statusbar();
2890
2891 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002892 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002893 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002894#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002895 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002896
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002897 UNSET(WHITESPACE_DISPLAY);
2898#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002899 bar = charalloc(COLS - 3);
2900 vsnprintf(bar, COLS - 3, msg, ap);
2901 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002902 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002903#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2904 if (old_whitespace)
2905 SET(WHITESPACE_DISPLAY);
2906#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002907 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002908 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002909 start_x = (COLS - foo_len - 4) / 2;
2910
2911 wmove(bottomwin, 0, start_x);
2912 wattron(bottomwin, A_REVERSE);
2913
2914 waddstr(bottomwin, "[ ");
2915 waddstr(bottomwin, foo);
2916 free(foo);
2917 waddstr(bottomwin, " ]");
2918 wattroff(bottomwin, A_REVERSE);
2919 wnoutrefresh(bottomwin);
2920 reset_cursor();
2921 wrefresh(edit);
2922 /* Leave the cursor at its position in the edit window, not
2923 * in the statusbar. */
2924 }
2925
2926 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002927 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002928}
2929
Chris Allegretta6232d662002-05-12 19:52:15 +00002930void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002931{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002932 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002933
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002934 if (ISSET(NO_HELP))
2935 return;
2936
Chris Allegretta6232d662002-05-12 19:52:15 +00002937 if (s == main_list) {
2938 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002939 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002940 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002941 slen = length_of_list(s);
2942
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002943 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002944 if (slen > MAIN_VISIBLE)
2945 slen = MAIN_VISIBLE;
2946 }
2947
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002948 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002949 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002950 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002951
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002952 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002953
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002954 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002955 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002956
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002957 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002958#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002959 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002960 keystr = _("Up");
2961 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002962#endif
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002963 char foo[4];
Chris Allegretta658399a2001-06-14 02:54:22 +00002964
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002965 if (s->ctrlval == NANO_CONTROL_SPACE)
2966 strcpy(foo, "^ ");
2967 else if (s->ctrlval == NANO_CONTROL_8)
2968 strcpy(foo, "^?");
2969 /* Normal values. Assume that the shortcut has an
2970 * equivalent control key, meta key sequence, or both. */
2971 else if (s->ctrlval != NANO_NO_KEY)
2972 sprintf(foo, "^%c", s->ctrlval + 64);
2973 else if (s->metaval != NANO_NO_KEY)
2974 sprintf(foo, "M-%c", toupper(s->metaval));
2975
2976 keystr = foo;
2977#ifndef NANO_SMALL
2978 }
2979#endif
2980
2981 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002982 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002983 }
2984
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002985 wnoutrefresh(bottomwin);
2986 reset_cursor();
2987 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002988}
2989
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002990/* Write a shortcut key to the help area at the bottom of the window.
2991 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2992 * to write at most len characters, even if len is very small and
2993 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2994 * the whole string! We do not bother padding the entry with blanks. */
2995void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002996{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002997 assert(keystroke != NULL && desc != NULL);
2998
2999 size_t keystroke_len = strlenpt(keystroke) + 1;
3000
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003001 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003002 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003003 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003004
3005 if (len > keystroke_len)
3006 len -= keystroke_len;
3007 else
3008 len = 0;
3009
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003010 if (len > 0) {
3011 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003012 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003013 }
3014}
3015
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003016/* And so start the display update routines. */
3017
3018#ifndef NDEBUG
3019int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003020{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003021 int check_line = 0;
3022 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00003023
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003024 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
3025 check_line++;
3026 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00003027}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003028#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00003029
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003030/* nano scrolls horizontally within a line in chunks. This function
3031 * returns the column number of the first character displayed in the
3032 * window when the cursor is at the given column. Note that
3033 * 0 <= column - get_page_start(column) < COLS. */
3034size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00003035{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003036 assert(COLS > 0);
3037 if (column == 0 || column < COLS - 1)
3038 return 0;
3039 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00003040 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003041 else if (COLS > 2)
3042 return column - (COLS - 2);
3043 else
3044 return column - (COLS - 1);
3045 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003046}
3047
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003048/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003049 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003050void reset_cursor(void)
3051{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003052 /* If we haven't opened any files yet, put the cursor in the top
3053 * left corner of the edit window and get out. */
3054 if (edittop == NULL || current == NULL) {
3055 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003056 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003057 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003058
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003059 current_y = current->lineno - edittop->lineno;
3060 if (current_y < editwinrows) {
3061 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003062 wmove(edit, current_y, x - get_page_start(x));
3063 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003064}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003065
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003066/* edit_add() takes care of the job of actually painting a line into the
3067 * edit window. fileptr is the line to be painted, at row yval of the
3068 * window. converted is the actual string to be written to the window,
3069 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003070 * characters. start is the column number of the first character of
3071 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003072 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003073void edit_add(const filestruct *fileptr, const char *converted, int
3074 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003075{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003076#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
3077 size_t startpos = actual_x(fileptr->data, start);
3078 /* The position in fileptr->data of the leftmost character
3079 * that displays at least partially on the window. */
3080 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3081 /* The position in fileptr->data of the first character that is
3082 * completely off the window to the right.
3083 *
3084 * Note that endpos might be beyond the null terminator of the
3085 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003086#endif
3087
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003088 assert(fileptr != NULL && converted != NULL);
3089 assert(strlen(converted) <= COLS);
3090
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003091 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003092 * just the text that needs it). */
3093 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003094
Chris Allegretta7dd77682001-12-08 19:52:28 +00003095#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00003096 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003097 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003098
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003099 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3100 int x_start;
3101 /* Starting column for mvwaddnstr. Zero-based. */
3102 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003103 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003104 * characters on a whole line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003105 regmatch_t startmatch; /* match position for start_regexp */
3106 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003107
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003108 if (tmpcolor->bright)
3109 wattron(edit, A_BOLD);
3110 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003111 /* Two notes about regexec(). Return value 0 means there is
3112 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003113 * after the match. */
3114
3115 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003116 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003117 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003118
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003119 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003120 * last match. Even though two matches may overlap, we
3121 * want to ignore them, so that we can highlight
3122 * C-strings correctly. */
3123 while (k < endpos) {
3124 /* Note the fifth parameter to regexec(). It says
3125 * not to match the beginning-of-line character
3126 * unless k is 0. If regexec() returns REG_NOMATCH,
3127 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003128 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003129 &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003130 break;
3131 /* Translate the match to the beginning of the line. */
3132 startmatch.rm_so += k;
3133 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003134 if (startmatch.rm_so == startmatch.rm_eo) {
3135 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00003136 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003137 } else if (startmatch.rm_so < endpos &&
3138 startmatch.rm_eo > startpos) {
3139 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003140 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003141 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003142 x_start = strnlenpt(fileptr->data,
3143 startmatch.rm_so) - start;
3144 paintlen = strnlenpt(fileptr->data,
3145 startmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003146 if (paintlen > COLS - x_start)
3147 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003148
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003149 assert(0 <= x_start && 0 < paintlen &&
3150 x_start + paintlen <= COLS);
3151 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003152 converted + x_start, paintlen);
3153 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003154 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003155 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003156 } else {
3157 /* This is a multi-line regexp. There are two steps.
3158 * First, we have to see if the beginning of the line is
3159 * colored by a start on an earlier line, and an end on
3160 * this line or later.
3161 *
3162 * We find the first line before fileptr matching the
3163 * start. If every match on that line is followed by an
3164 * end, then go to step two. Otherwise, find the next line
3165 * after start_line matching the end. If that line is not
3166 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003167
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003168 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003169 /* the first line before fileptr matching start */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003170 regoff_t start_col;
3171 /* where it starts in that line */
3172 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003173
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003174 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003175 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003176 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003177 /* If there is an end on this line, there is no need
3178 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003179 if (regexec(tmpcolor->end, start_line->data, 0,
3180 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003181 goto step_two;
3182 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003183 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003184 /* No start found, so skip to the next step. */
3185 if (start_line == NULL)
3186 goto step_two;
3187 /* Now start_line is the first line before fileptr
3188 * containing a start match. Is there a start on this
3189 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003190
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003191 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003192 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003193 start_col += startmatch.rm_so;
3194 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003195 if (regexec(tmpcolor->end,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003196 start_line->data + start_col + startmatch.rm_eo,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003197 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
3198 REG_NOTBOL) == REG_NOMATCH)
3199 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003200 break;
3201 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003202 if (regexec(&tmpcolor->start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003203 start_line->data + start_col, 1,
3204 &startmatch, REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003205 /* No later start on this line. */
3206 goto step_two;
3207 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003208 /* Indeed, there is a start not followed on this line by
3209 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003210
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003211 /* We have already checked that there is no end before
3212 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003213 * the start at all? We don't paint unterminated
3214 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003215 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003216 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003217 regexec(tmpcolor->end, end_line->data, 1,
3218 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003219 end_line = end_line->next;
3220
3221 /* No end found, or it is too early. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003222 if (end_line == NULL ||
3223 (end_line == fileptr && endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003224 goto step_two;
3225
3226 /* Now paint the start of fileptr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003227 paintlen = end_line != fileptr ? COLS :
3228 strnlenpt(fileptr->data, endmatch.rm_eo) - start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003229 if (paintlen > COLS)
3230 paintlen = COLS;
3231
3232 assert(0 < paintlen && paintlen <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003233 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003234
3235 /* We have already painted the whole line. */
3236 if (paintlen == COLS)
3237 goto skip_step_two;
3238
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003239 step_two:
3240 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003241 start_col = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003242 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003243 if (regexec(&tmpcolor->start,
3244 fileptr->data + start_col, 1, &startmatch,
3245 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
3246 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003247 /* No more starts on this line. */
3248 break;
3249 /* Translate the match to be relative to the
3250 * beginning of the line. */
3251 startmatch.rm_so += start_col;
3252 startmatch.rm_eo += start_col;
3253
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003254 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003255 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003256 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003257 x_start = strnlenpt(fileptr->data,
3258 startmatch.rm_so) - start;
3259 if (regexec(tmpcolor->end,
3260 fileptr->data + startmatch.rm_eo, 1, &endmatch,
3261 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003262 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003263 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003264 endmatch.rm_so += startmatch.rm_eo;
3265 endmatch.rm_eo += startmatch.rm_eo;
3266 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003267 * appear on this page, and is the match more
3268 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003269 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003270 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003271 paintlen = strnlenpt(fileptr->data,
3272 endmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003273 if (x_start + paintlen > COLS)
3274 paintlen = COLS - x_start;
3275
3276 assert(0 <= x_start && 0 < paintlen &&
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003277 x_start + paintlen <= COLS);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003278 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003279 converted + x_start, 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 Ramsey5ffbec52003-09-16 01:16:49 +00003285 while (end_line != NULL &&
3286 regexec(tmpcolor->end, end_line->data, 0,
3287 NULL, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003288 end_line = end_line->next;
3289 if (end_line != NULL) {
3290 assert(0 <= x_start && x_start < COLS);
3291 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003292 converted + x_start, COLS - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003293 /* We painted to the end of the line, so
3294 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003295 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003296 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003297 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003298 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003299 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003300 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003301
Chris Allegrettace452fb2003-02-03 02:56:44 +00003302 skip_step_two:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003303 wattroff(edit, A_BOLD);
3304 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
3305 } /* for tmpcolor in colorstrings */
3306 }
Chris Allegretta598106e2002-01-19 01:59:37 +00003307#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003308
Chris Allegretta7dd77682001-12-08 19:52:28 +00003309#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003310 if (ISSET(MARK_ISSET)
3311 && (fileptr->lineno <= mark_beginbuf->lineno
3312 || fileptr->lineno <= current->lineno)
3313 && (fileptr->lineno >= mark_beginbuf->lineno
3314 || fileptr->lineno >= current->lineno)) {
3315 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003316
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003317 const filestruct *top;
3318 /* Either current or mark_beginbuf, whichever is first. */
3319 size_t top_x;
3320 /* current_x or mark_beginx, corresponding to top. */
3321 const filestruct *bot;
3322 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003323 int x_start;
3324 /* Starting column for mvwaddnstr. Zero-based. */
3325 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003326 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003327 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003328
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003329 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003330
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003331 if (top->lineno < fileptr->lineno || top_x < startpos)
3332 top_x = startpos;
3333 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3334 bot_x = endpos;
3335
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003336 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003337 if (top_x < endpos && bot_x > startpos) {
3338 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003339
3340 /* x_start is the expanded location of the beginning of the
3341 * mark minus the beginning of the page. */
3342 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003343
3344 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003345 /* If the end of the mark is off the page, paintlen is
3346 * -1, meaning that everything on the line gets
3347 * painted. */
3348 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003349 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003350 /* Otherwise, paintlen is the expanded location of the
3351 * end of the mark minus the expanded location of the
3352 * beginning of the mark. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003353 paintlen = strnlenpt(fileptr->data, bot_x)
3354 - (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003355
3356 /* If x_start is before the beginning of the page, shift
3357 * paintlen x_start characters to compensate, and put
3358 * x_start at the beginning of the page. */
3359 if (x_start < 0) {
3360 paintlen += x_start;
3361 x_start = 0;
3362 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003363
3364 assert(x_start >= 0 && x_start <= strlen(converted));
3365
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003366 wattron(edit, A_REVERSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003367 mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003368 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003369 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003370 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003371#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003372}
3373
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003374/* Just update one line in the edit buffer. This is basically a wrapper
3375 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003376 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003377 * If fileptr != current, then index is considered 0. The line will be
3378 * displayed starting with fileptr->data[index]. Likely args are
3379 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003380void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003381{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003382 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003383 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003384 char *converted;
3385 /* fileptr->data converted to have tabs and control characters
3386 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003387 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003388
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003389 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003390
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003391 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003392
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003393 /* We assume the line numbers are valid. Is that really true? */
3394 assert(line < 0 || line == check_linenumbers(fileptr));
3395
3396 if (line < 0 || line >= editwinrows)
3397 return;
3398
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003399 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003400 mvwaddstr(edit, line, 0, hblank);
3401
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003402 /* Next, convert variables that index the line to their equivalent
3403 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003404 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003405 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003406
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003407 /* Expand the line, replacing tabs with spaces, and control
3408 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003409 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003410
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003411 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003412 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003413 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003414
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003415 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003416 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003417 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003418 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003419}
3420
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003421/* Return a nonzero value if we need an update after moving
3422 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003423 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003424int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003425{
3426 return
3427#ifndef NANO_SMALL
3428 ISSET(MARK_ISSET) ||
3429#endif
3430 get_page_start(old_pww) != get_page_start(placewewant);
3431}
3432
3433/* Return a nonzero value if we need an update after moving vertically.
3434 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003435 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003436int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003437{
3438 return
3439#ifndef NANO_SMALL
3440 ISSET(MARK_ISSET) ||
3441#endif
3442 get_page_start(old_pww) != get_page_start(placewewant);
3443}
3444
3445/* Scroll the edit window in the given direction and the given number
3446 * of lines, and draw new lines on the blank lines left after the
3447 * scrolling. direction is the direction to scroll, either UP or DOWN,
3448 * and nlines is the number of lines to scroll. Don't redraw the old
3449 * topmost or bottommost line (where we assume current is) before
3450 * scrolling or draw the new topmost or bottommost line after scrolling
3451 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003452 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003453void edit_scroll(updown direction, int nlines)
3454{
3455 filestruct *foo;
3456 int i, scroll_rows = 0;
3457
3458 /* Scrolling less than one line or more than editwinrows lines is
3459 * redundant, so don't allow it. */
3460 if (nlines < 1 || nlines > editwinrows)
3461 return;
3462
3463 /* Move the top line of the edit window up or down (depending on the
3464 * value of direction) nlines lines. If there are fewer lines of
3465 * text than that left, move it to the top or bottom line of the
3466 * file (depending on the value of direction). Keep track of
3467 * how many lines we moved in scroll_rows. */
3468 for (i = nlines; i > 0; i--) {
3469 if (direction == UP) {
3470 if (edittop->prev == NULL)
3471 break;
3472 edittop = edittop->prev;
3473 scroll_rows--;
3474 } else {
3475 if (edittop->next == NULL)
3476 break;
3477 edittop = edittop->next;
3478 scroll_rows++;
3479 }
3480 }
3481
3482 /* Scroll the text on the screen up or down scroll_rows lines,
3483 * depending on the value of direction. */
3484 scrollok(edit, TRUE);
3485 wscrl(edit, scroll_rows);
3486 scrollok(edit, FALSE);
3487
3488 foo = edittop;
3489 if (direction != UP) {
3490 int slines = editwinrows - nlines;
3491 for (; slines > 0 && foo != NULL; slines--)
3492 foo = foo->next;
3493 }
3494
3495 /* And draw new lines on the blank top or bottom lines of the edit
3496 * window, depending on the value of direction. Don't draw the new
3497 * topmost or new bottommost line. */
3498 while (scroll_rows != 0 && foo != NULL) {
3499 if (foo->next != NULL)
3500 update_line(foo, 0);
3501 if (direction == UP)
3502 scroll_rows++;
3503 else
3504 scroll_rows--;
3505 foo = foo->next;
3506 }
3507}
3508
3509/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003510 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003511void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003512{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003513 int do_refresh = need_vertical_update(0) ||
3514 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003515 const filestruct *foo;
3516
3517 /* If either old_current or current is offscreen, refresh the screen
3518 * and get out. */
3519 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3520 edittop->lineno + editwinrows || current->lineno <
3521 edittop->lineno || current->lineno >= edittop->lineno +
3522 editwinrows) {
3523 edit_refresh();
3524 return;
3525 }
3526
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003527 /* Update old_current and current if we're not on the first page
3528 * and/or we're not on the same page as before. If the mark is on,
3529 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003530 foo = old_current;
3531 while (foo != current) {
3532 if (do_refresh)
3533 update_line(foo, 0);
3534#ifndef NANO_SMALL
3535 if (!ISSET(MARK_ISSET))
3536#endif
3537 break;
3538 if (foo->lineno > current->lineno)
3539 foo = foo->prev;
3540 else
3541 foo = foo->next;
3542 }
3543 if (do_refresh)
3544 update_line(current, current_x);
3545}
3546
Chris Allegretta6df90f52002-07-19 01:08:59 +00003547/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003548void edit_refresh(void)
3549{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003550 if (current->lineno < edittop->lineno ||
3551 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003552 /* Note that edit_update() changes edittop so that it's in range
3553 * of current. Thus, when it then calls edit_refresh(), there
3554 * is no danger of getting an infinite loop. */
3555 edit_update(
3556#ifndef NANO_SMALL
3557 ISSET(SMOOTHSCROLL) ? NONE :
3558#endif
3559 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003560 else {
3561 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003562 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003563
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003564#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003565 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003566#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003567
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003568 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003569 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003570 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003571 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003572 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003573 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003574 }
3575 while (nlines < editwinrows) {
3576 mvwaddstr(edit, nlines, 0, hblank);
3577 nlines++;
3578 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003579 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003580 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003581 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003582}
3583
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003584/* A nice generic routine to update the edit buffer. We keep current in
3585 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003586void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003587{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003588 filestruct *foo = current;
3589
Chris Allegretta6df90f52002-07-19 01:08:59 +00003590 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003591 /* If location is CENTER, we move edittop up (editwinrows / 2)
3592 * lines. This puts current at the center of the screen. If
3593 * location is NONE, we move edittop up current_y lines if
3594 * current_y is in range of the screen, 0 lines if current_y is
3595 * less than 0, or (editwinrows - 1) lines if current_y is
3596 * greater than (editwinrows - 1). This puts current at the
3597 * same place on the screen as before, or at the top or bottom
3598 * of the screen if edittop is beyond either. */
3599 int goal;
3600
3601 if (location == CENTER)
3602 goal = editwinrows / 2;
3603 else {
3604 goal = current_y;
3605
3606 /* Limit goal to (editwinrows - 1) lines maximum. */
3607 if (goal > editwinrows - 1)
3608 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003609 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003610
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003611 for (; goal > 0 && foo->prev != NULL; goal--)
3612 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003613 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003614
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003615 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003616 edit_refresh();
3617}
3618
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003619/* Ask a simple yes/no question, specified in msg, on the statusbar.
3620 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3621 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003622int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003623{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003624 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003625 const char *yesstr; /* String of yes characters accepted. */
3626 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003627 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003628
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003629 /* yesstr, nostr, and allstr are strings of any length. Each string
3630 * consists of all characters accepted as a valid character for that
3631 * value. The first value will be the one displayed in the
3632 * shortcuts. Translators: if possible, specify both the shortcuts
3633 * for your language and English. For example, in French: "OoYy"
3634 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003635 yesstr = _("Yy");
3636 nostr = _("Nn");
3637 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003638
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003639 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003640 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003641
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003642 if (COLS < 32)
3643 width = COLS / 2;
3644
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003645 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003646 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003647
Chris Allegretta6232d662002-05-12 19:52:15 +00003648 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003649 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003650 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003651
3652 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003653 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003654 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003655 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003656 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003657
Chris Allegrettadb28e962003-01-28 01:23:40 +00003658 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003659 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003660 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003661
Chris Allegrettadb28e962003-01-28 01:23:40 +00003662 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003663 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003664 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003665
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003666 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003667
3668 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003669 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003670
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003671 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003672
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003673 wrefresh(bottomwin);
3674
Chris Allegrettadb28e962003-01-28 01:23:40 +00003675 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003676 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003677 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003678#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003679 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003680#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003681
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003682 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003683
3684 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003685 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003686#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003687 /* Look, ma! We get to duplicate lots of code from
3688 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003689 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003690 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003691
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003692 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003693 wenclose(bottomwin, mouse_y, mouse_x) &&
3694 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003695 int x = mouse_x / width;
3696 /* Did we click in the first column of shortcuts, or
3697 * the second? */
3698 int y = mouse_y - editwinrows - 3;
3699 /* Did we click in the first row of shortcuts? */
3700
3701 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3702
3703 /* x = 0 means they clicked Yes or No.
3704 * y = 0 means Yes or All. */
3705 ok = -2 * x * y + x - y + 1;
3706
3707 if (ok == 2 && !all)
3708 ok = -2;
3709 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003710 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003711#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003712 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003713 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003714 else if (strchr(yesstr, kbinput) != NULL)
3715 ok = 1;
3716 else if (strchr(nostr, kbinput) != NULL)
3717 ok = 0;
3718 else if (all && strchr(allstr, kbinput) != NULL)
3719 ok = 2;
3720 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003721
Chris Allegrettadb28e962003-01-28 01:23:40 +00003722 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003723}
3724
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003725void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003726{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003727 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003728 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003729 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003730 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003731 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003732 wnoutrefresh(bottomwin);
3733 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003734 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003735 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003736 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003737 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003738 edit_refresh();
3739 /* FIXME: bottomwin needs to be refreshed too. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003740}
3741
3742void display_main_list(void)
3743{
3744 bottombars(main_list);
3745}
3746
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003747/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3748 * display the cursor position. Otherwise, we display it only if the
3749 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003750 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003751 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3752 * old_i and old_totsize. That way, we leave the current statusbar
3753 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003754void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003755{
Chris Allegrettad26ab912003-01-28 01:16:47 +00003756 const filestruct *fileptr;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003757 size_t i = 0;
3758 static size_t old_i = 0;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003759 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003760
Chris Allegrettad26ab912003-01-28 01:16:47 +00003761 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003762
3763 if (old_totsize == -1)
3764 old_totsize = totsize;
3765
Chris Allegrettad26ab912003-01-28 01:16:47 +00003766 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
3767 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003768 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003769 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003770 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003771
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003772 /* Check whether totsize is correct. Else there is a bug
3773 * somewhere. */
3774 assert(current != filebot || i == totsize);
3775
Chris Allegrettad26ab912003-01-28 01:16:47 +00003776 if (constant && ISSET(DISABLE_CURPOS)) {
3777 UNSET(DISABLE_CURPOS);
3778 old_i = i;
3779 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003780 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003781 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003782
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003783 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003784 * unconditionally; otherwise, only display the position when the
3785 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003786 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003787 size_t xpt = xplustabs() + 1;
3788 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003789 int linepct = 100 * current->lineno / totlines;
3790 int colpct = 100 * xpt / cur_len;
3791 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
3792
3793 statusbar(
3794 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3795 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003796 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003797 (unsigned long)i, totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003798 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003799 }
3800
3801 old_i = i;
3802 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003803}
3804
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003805void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003806{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003807 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003808}
3809
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003810#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003811/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003812int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003813{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003814 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003815
3816 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3817 ptr++;
3818 j++;
3819 }
3820 if (j == COLS - 5) {
3821 /* Don't wrap at the first of two spaces following a period. */
3822 if (*ptr == ' ' && *(ptr + 1) == ' ')
3823 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003824 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003825 while (*ptr != ' ' && j > 0) {
3826 ptr--;
3827 j--;
3828 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003829 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003830 if (j == 0)
3831 j = COLS - 5;
3832 }
3833 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
3834 return j;
3835}
3836
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003837/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003838void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003839{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003840 int line = 0;
3841 /* The line number in help_text of the first displayed help line.
3842 * This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003843 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003844 /* no_more means the end of the help text is shown, so don't go
3845 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003846 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003847 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003848
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003849 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003850#ifndef DISABLE_MOUSE
3851 const shortcut *oldshortcut = currshortcut;
3852 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003853 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003854#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003855
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003856 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003857 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003858 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003859 blank_statusbar();
3860
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003861 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003862 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003863 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003864
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003865#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003866 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003867 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003868 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003869#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003870
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003871 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003872 /* Make sure that the help screen's shortcut list will actually
3873 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003874 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003875 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003876 }
3877 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003878
3879 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003880 int i;
3881 int old_line = line;
3882 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003883 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003884
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003885 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003886#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003887 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003888 {
3889 int mouse_x, mouse_y;
3890 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3891 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003892 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003893#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003894 case NANO_NEXTPAGE_KEY:
3895 case NANO_NEXTPAGE_FKEY:
3896 if (!no_more)
3897 line += editwinrows - 2;
3898 break;
3899 case NANO_PREVPAGE_KEY:
3900 case NANO_PREVPAGE_FKEY:
3901 if (line > 0) {
3902 line -= editwinrows - 2;
3903 if (line < 0)
3904 line = 0;
3905 }
3906 break;
3907 case NANO_PREVLINE_KEY:
3908 if (line > 0)
3909 line--;
3910 break;
3911 case NANO_NEXTLINE_KEY:
3912 if (!no_more)
3913 line++;
3914 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003915 }
3916
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003917 if (line == old_line && kbinput != ERR)
3918 goto skip_redisplay;
3919
3920 blank_edit();
3921
3922 assert(COLS > 5);
3923
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003924 /* Calculate where in the text we should be, based on the
3925 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003926 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003927 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003928 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003929 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003930 }
3931
Chris Allegretta4640fe32003-02-10 03:10:03 +00003932 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003933 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003934
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003935 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003936 ptr += j;
3937 if (*ptr == '\n')
3938 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003939 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003940 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003941
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003942 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003943 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003944 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3945 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003946
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003947#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003948 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003949#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003950
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003951 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003952 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003953 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003954 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003955 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003956 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003957 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003958
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003959 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003960 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003961
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003962 /* The help_init() at the beginning allocated help_text. Since
3963 * help_text has now been written to the screen, we don't need it
3964 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003965 free(help_text);
3966 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003967}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003968#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003969
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003970/* Highlight the current word being replaced or spell checked. We
3971 * expect word to have tabs and control characters expanded. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003972void do_replace_highlight(int highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003973{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003974 size_t y = xplustabs();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003975 size_t word_len = strlen(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003976
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003977 y = get_page_start(y) + COLS - y;
3978 /* Now y is the number of characters we can display on this
3979 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003980
3981 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003982
Chris Allegrettafb62f732000-12-05 11:36:41 +00003983 if (highlight_flag)
3984 wattron(edit, A_REVERSE);
3985
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003986#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003987 /* This is so we can show zero-length regexes. */
3988 if (word_len == 0)
3989 waddstr(edit, " ");
3990 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003991#endif
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003992 waddnstr(edit, word, y - 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003993
3994 if (word_len > y)
3995 waddch(edit, '$');
3996 else if (word_len == y)
3997 waddch(edit, word[word_len - 1]);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003998
3999 if (highlight_flag)
4000 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004001}
4002
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004003#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004004/* Dump the passed-in file structure to stderr. */
4005void dump_buffer(const filestruct *inptr)
4006{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004007 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004008 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004009 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004010 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004011 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00004012 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004013
4014 while (inptr != NULL) {
4015 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4016 inptr = inptr->next;
4017 }
4018}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004019
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004020/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004021void dump_buffer_reverse(void)
4022{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004023 const filestruct *fileptr = filebot;
4024
4025 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004026 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004027 fileptr = fileptr->prev;
4028 }
4029}
4030#endif /* DEBUG */
4031
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004032#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004033#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004034#define XLCREDIT_LEN 8
4035
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004036/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004037void do_credits(void)
4038{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004039 int crpos = 0, xlpos = 0;
4040 const char *credits[CREDIT_LEN] = {
4041 NULL, /* "The nano text editor" */
4042 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004043 VERSION,
4044 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004045 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004046 "Chris Allegretta",
4047 "Jordi Mallach",
4048 "Adam Rogoyski",
4049 "Rob Siemborski",
4050 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004051 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004052 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004053 "Ken Tyler",
4054 "Sven Guckes",
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004055#ifdef NANO_WIDE
4056 !ISSET(NO_UTF8) ? "Florian K\xC3\xB6nig" :
4057#endif
4058 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00004059 "Pauli Virtanen",
4060 "Daniele Medri",
4061 "Clement Laforet",
4062 "Tedi Heriyanto",
4063 "Bill Soudan",
4064 "Christian Weisgerber",
4065 "Erik Andersen",
4066 "Big Gaute",
4067 "Joshua Jensen",
4068 "Ryan Krebs",
4069 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004070 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004071 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004072 "Plattsburgh State University",
4073 "Benet Laboratories",
4074 "Amy Allegretta",
4075 "Linda Young",
4076 "Jeremy Robichaud",
4077 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004078 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004079 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004080 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004081 "Thomas Dickey",
4082 "Pavel Curtis",
4083 "Zeyd Ben-Halim",
4084 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004085 NULL, /* "and anyone else we forgot..." */
4086 NULL, /* "Thank you for using nano!" */
4087 "",
4088 "",
4089 "",
4090 "",
David Lawrence Ramsey6481c3f2004-01-09 23:06:54 +00004091 "(c) 1999-2004 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004092 "",
4093 "",
4094 "",
4095 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004096 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004097 };
4098
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004099 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004100 N_("The nano text editor"),
4101 N_("version"),
4102 N_("Brought to you by:"),
4103 N_("Special thanks to:"),
4104 N_("The Free Software Foundation"),
4105 N_("For ncurses:"),
4106 N_("and anyone else we forgot..."),
4107 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004108 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004109
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004110 curs_set(0);
4111 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004112 scrollok(edit, TRUE);
4113 blank_titlebar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004114 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004115 blank_statusbar();
4116 blank_bottombars();
4117 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004118 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004119 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004120
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004121 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
4122 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004123 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004124 if (crpos < CREDIT_LEN) {
4125 const char *what = credits[crpos];
4126 size_t start_x;
4127
4128 if (what == NULL) {
4129 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00004130 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004131 xlpos++;
4132 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004133 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramseyeb711b02004-12-05 22:24:39 +00004134 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x,
4135 what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004136 }
4137 napms(700);
4138 scroll(edit);
4139 wrefresh(edit);
4140 if (wgetch(edit) != ERR)
4141 break;
4142 napms(700);
4143 scroll(edit);
4144 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004145 }
4146
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004147 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004148 nodelay(edit, FALSE);
4149 curs_set(1);
4150 display_main_list();
4151 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004152}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004153#endif