blob: 4875f5fa8a71c266ce674a854cd8846950fc1871 [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * winio.c *
4 * *
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00005 * Copyright (C) 1999-2005 Chris Allegretta *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00006 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * any later version. *
10 * *
David Lawrence Ramsey6e925cf2005-05-15 19:57:17 +000011 * This program is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * General Public License for more details. *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000015 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
David Lawrence Ramsey6e925cf2005-05-15 19:57:17 +000018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
19 * 02110-1301, USA. *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000020 * *
21 **************************************************************************/
22
Jordi Mallach55381aa2004-11-17 23:17:05 +000023#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000026
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000027#include <stdarg.h>
28#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000029#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000030#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000031#include <ctype.h>
Chris Allegretta6232d662002-05-12 19:52:15 +000032#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000033#include "proto.h"
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000034
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +000035static int *key_buffer = NULL;
David Lawrence Ramsey74835712004-12-04 17:41:52 +000036 /* The default keystroke buffer,
37 * containing all the keystrokes we have
38 * at a given point. */
39static size_t key_buffer_len = 0;
40 /* The length of the default keystroke
41 * buffer. */
42static int statusblank = 0; /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000043 * we call statusbar(), before we
44 * actually blank the statusbar. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +000045static size_t statusbar_x = (size_t)-1;
46 /* The cursor position in answer. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000047static bool resetstatuspos = FALSE;
48 /* Should we reset the cursor position
49 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000050
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000051/* Control character compatibility:
52 *
53 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
54 * VT100, and VT220.
55 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
56 * VT220, and VT320.
57 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
58 * VT220, and VT320.
59 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
60 * VT220, and VT320.
61 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
62 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000063 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000064 * ANSI, VT100, and VT220, and which is Backspace under VT320.
65 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000066 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000067 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
68 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000069 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000070 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000071 * on which the VT320 sequences are translated by the keypad to KEY_DC
72 * and [nothing]. We work around this conflict via the REBIND_DELETE
73 * flag: if it's not set, we assume VT320 compatibility, and if it is,
74 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
75 * Hemel for helping work this conflict out.
76 *
77 * Escape sequence compatibility:
78 *
79 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000080 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000081 * console), xterm, rxvt, and Eterm. Among these, there are several
82 * conflicts and omissions, outlined as follows:
83 *
84 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
85 * (Ctrl-I is also Tab on ANSI, which we already support.)
86 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
87 * NumLock off on Linux console; the latter is omitted. (The editing
88 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000089 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000090 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
91 * latter is omitted. (Mouse input will only work properly if the
92 * extended keypad value KEY_MOUSE is generated on mouse events
93 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000094 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000095 * omitted. (The editing keypad is more important to have working
96 * than the function keys, because the functions of the former are not
97 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000098 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000099 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000100 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000101 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000102 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
103 * omitted. (The arrow keys, with or without modifiers, are more
104 * important to have working than the function keys, because the
105 * functions of the former are not arbitrary and the functions of the
106 * latter are.)
107 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
108 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000109 *
110 * Note that Center (5) on the numeric keypad with NumLock off can also
111 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000112
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000113#ifndef NANO_SMALL
114/* Reset all the input routines that rely on character sequences. */
115void reset_kbinput(void)
116{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000117 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000118 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000119 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000120}
121#endif
122
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000123/* Read in a sequence of keystrokes from win and save them in the
124 * default keystroke buffer. This should only be called when the
125 * default keystroke buffer is empty. */
126void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000127{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000128 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000129
130 /* If the keystroke buffer isn't empty, get out. */
131 if (key_buffer != NULL)
132 return;
133
134 /* Read in the first character using blocking input. */
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000135#ifndef NANO_SMALL
136 allow_pending_sigwinch(TRUE);
137#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000138
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000139 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000140
David Lawrence Ramseyc275dc52005-03-08 17:45:36 +0000141 /* If we get ERR when using blocking input, it means that the input
142 * source that we were using is gone, so die gracefully. */
143 if (input == ERR)
144 handle_hupterm(0);
145
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000146#ifndef NANO_SMALL
147 allow_pending_sigwinch(FALSE);
148#endif
149
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000150 /* Increment the length of the keystroke buffer, save the value of
151 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000152 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000153 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000154 key_buffer = (int *)nmalloc(sizeof(int));
155 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000156
157 /* Read in the remaining characters using non-blocking input. */
158 nodelay(win, TRUE);
159
160 while (TRUE) {
161#ifndef NANO_SMALL
162 allow_pending_sigwinch(TRUE);
163#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000164
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000165 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000166
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000167 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000168 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000169 break;
170
171 /* Otherwise, increment the length of the keystroke buffer, save
172 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000173 * if the keystroke is an extended keypad value or FALSE if it
174 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000175 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000176 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
177 sizeof(int));
178 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000179
180#ifndef NANO_SMALL
181 allow_pending_sigwinch(FALSE);
182#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000183 }
184
185 /* Switch back to non-blocking input. */
186 nodelay(win, FALSE);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000187
188#ifdef DEBUG
189 fprintf(stderr, "get_buffer(): key_buffer_len = %lu\n", (unsigned long)key_buffer_len);
190#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000191}
192
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000193/* Return the length of the default keystroke buffer. */
194size_t get_buffer_len(void)
195{
196 return key_buffer_len;
197}
198
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000199/* Add the contents of the keystroke buffer input to the default
200 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000201void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000202{
203#ifndef NANO_SMALL
204 allow_pending_sigwinch(TRUE);
205 allow_pending_sigwinch(FALSE);
206#endif
207
208 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000209 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000210 return;
211
212 /* If adding input would put the default keystroke buffer beyond
213 * maximum capacity, only add enough of input to put it at maximum
214 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000215 if (key_buffer_len + input_len < key_buffer_len)
216 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000217
218 /* Add the length of input to the length of the default keystroke
219 * buffer, and reallocate the default keystroke buffer so that it
220 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000221 key_buffer_len += input_len;
222 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
223 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000224
225 /* If the default keystroke buffer wasn't empty before, move its
226 * beginning forward far enough so that we can add input to its
227 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000228 if (key_buffer_len > input_len)
229 memmove(key_buffer + input_len, key_buffer,
230 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000231
232 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000233 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000234}
235
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000236/* Put back the character stored in kbinput, putting it in byte range
237 * beforehand. If meta_key is TRUE, put back the Escape character after
238 * putting back kbinput. If func_key is TRUE, put back the function key
239 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000240void unget_kbinput(int kbinput, bool meta_key, bool func_key)
241{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000242 if (!func_key)
243 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000244
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000245 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000246
247 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000248 kbinput = NANO_CONTROL_3;
249 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000250 }
251}
252
253/* Try to read input_len characters from the default keystroke buffer.
254 * If the default keystroke buffer is empty and win isn't NULL, try to
255 * read in more characters from win and add them to the default
256 * keystroke buffer before doing anything else. If the default
257 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000258int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000259{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000260 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000261
262#ifndef NANO_SMALL
263 allow_pending_sigwinch(TRUE);
264 allow_pending_sigwinch(FALSE);
265#endif
266
267 if (key_buffer_len == 0) {
268 if (win != NULL)
269 get_buffer(win);
270
271 if (key_buffer_len == 0)
272 return NULL;
273 }
274
275 /* If input_len is greater than the length of the default keystroke
276 * buffer, only read the number of characters in the default
277 * keystroke buffer. */
278 if (input_len > key_buffer_len)
279 input_len = key_buffer_len;
280
281 /* Subtract input_len from the length of the default keystroke
282 * buffer, and allocate the keystroke buffer input so that it
283 * has enough room for input_len keystrokes. */
284 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000285 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000286
287 /* Copy input_len characters from the beginning of the default
288 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000289 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000290
291 /* If the default keystroke buffer is empty, mark it as such. */
292 if (key_buffer_len == 0) {
293 free(key_buffer);
294 key_buffer = NULL;
295 /* If the default keystroke buffer isn't empty, move its
296 * beginning forward far enough back so that the keystrokes in input
297 * are no longer at its beginning. */
298 } else {
299 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000300 sizeof(int));
301 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
302 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000303 }
304
305 return input;
306}
307
308/* Read in a single character. If it's ignored, swallow it and go on.
309 * Otherwise, try to translate it from ASCII, meta key sequences, escape
310 * sequences, and/or extended keypad values. Set meta_key to TRUE when
311 * we get a meta key sequence, and set func_key to TRUE when we get an
312 * extended keypad value. Supported extended keypad values consist of
313 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
314 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
315 * the function keypad (F1-F16), and the numeric keypad with NumLock
316 * off. Assume nodelay(win) is FALSE. */
317int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
318{
319 int kbinput;
320
321 /* Read in a character and interpret it. Continue doing this until
322 * we get a recognized value or sequence. */
323 while ((kbinput = parse_kbinput(win, meta_key, func_key
324#ifndef NANO_SMALL
325 , FALSE
326#endif
327 )) == ERR);
328
329 return kbinput;
330}
331
332/* Translate ASCII characters, extended keypad values, and escape
333 * sequences into their corresponding key values. Set meta_key to TRUE
334 * when we get a meta key sequence, and set func_key to TRUE when we get
335 * a function key. Assume nodelay(win) is FALSE. */
336int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000337#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000338 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000339#endif
340 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000341
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000342{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000343 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000344 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000345
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000346#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000347 if (reset) {
348 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000349 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000350 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000351 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000352#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000353
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000354 *meta_key = FALSE;
355 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000356
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000357 /* Read in a character. */
358 while ((kbinput = get_input(win, 1)) == NULL);
359
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000360 switch (*kbinput) {
361 case ERR:
362 break;
363 case NANO_CONTROL_3:
364 /* Increment the escape counter. */
365 escapes++;
366 switch (escapes) {
367 case 1:
368 /* One escape: wait for more input. */
369 case 2:
370 /* Two escapes: wait for more input. */
371 break;
372 default:
373 /* More than two escapes: reset the escape counter
374 * and wait for more input. */
375 escapes = 0;
376 }
377 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000378#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000379 /* Since we don't change the default SIGWINCH handler when
380 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
381 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
382 case KEY_RESIZE:
383 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000384#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000385#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000386 case KEY_SHIFT_L:
387 case KEY_SHIFT_R:
388 case KEY_CONTROL_L:
389 case KEY_CONTROL_R:
390 case KEY_ALT_L:
391 case KEY_ALT_R:
392 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000393#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000394 default:
395 switch (escapes) {
396 case 0:
397 switch (*kbinput) {
398 case NANO_CONTROL_8:
399 retval = ISSET(REBIND_DELETE) ?
400 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
401 break;
402 case KEY_DOWN:
403 retval = NANO_NEXTLINE_KEY;
404 break;
405 case KEY_UP:
406 retval = NANO_PREVLINE_KEY;
407 break;
408 case KEY_LEFT:
409 retval = NANO_BACK_KEY;
410 break;
411 case KEY_RIGHT:
412 retval = NANO_FORWARD_KEY;
413 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000414#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000415 /* HP-UX 10 and 11 don't support KEY_HOME. */
416 case KEY_HOME:
417 retval = NANO_HOME_KEY;
418 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000419#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000420 case KEY_BACKSPACE:
421 retval = NANO_BACKSPACE_KEY;
422 break;
423 case KEY_DC:
424 retval = ISSET(REBIND_DELETE) ?
425 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
426 break;
427 case KEY_IC:
428 retval = NANO_INSERTFILE_KEY;
429 break;
430 case KEY_NPAGE:
431 retval = NANO_NEXTPAGE_KEY;
432 break;
433 case KEY_PPAGE:
434 retval = NANO_PREVPAGE_KEY;
435 break;
436 case KEY_ENTER:
437 retval = NANO_ENTER_KEY;
438 break;
439 case KEY_A1: /* Home (7) on numeric keypad
440 * with NumLock off. */
441 retval = NANO_HOME_KEY;
442 break;
443 case KEY_A3: /* PageUp (9) on numeric keypad
444 * with NumLock off. */
445 retval = NANO_PREVPAGE_KEY;
446 break;
447 case KEY_B2: /* Center (5) on numeric keypad
448 * with NumLock off. */
449 break;
450 case KEY_C1: /* End (1) on numeric keypad
451 * with NumLock off. */
452 retval = NANO_END_KEY;
453 break;
454 case KEY_C3: /* PageDown (4) on numeric
455 * keypad with NumLock off. */
456 retval = NANO_NEXTPAGE_KEY;
457 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000458#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000459 /* Slang doesn't support KEY_BEG. */
460 case KEY_BEG: /* Center (5) on numeric keypad
461 * with NumLock off. */
462 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000463#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000464#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000465 /* HP-UX 10 and 11 don't support KEY_END. */
466 case KEY_END:
467 retval = NANO_END_KEY;
468 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000469#endif
470#ifdef KEY_SUSPEND
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000471 /* Slang doesn't support KEY_SUSPEND. */
472 case KEY_SUSPEND:
473 retval = NANO_SUSPEND_KEY;
474 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000475#endif
476#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000477 /* Slang doesn't support KEY_SLEFT. */
478 case KEY_SLEFT:
479 retval = NANO_BACK_KEY;
480 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000481#endif
482#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000483 /* Slang doesn't support KEY_SRIGHT. */
484 case KEY_SRIGHT:
485 retval = NANO_FORWARD_KEY;
486 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000487#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000488 default:
489 retval = *kbinput;
490 break;
491 }
492 break;
493 case 1:
494 /* One escape followed by a non-escape: escape
495 * sequence mode. Reset the escape counter. If
496 * there aren't any other keys waiting, we have a
497 * meta key sequence, so set meta_key to TRUE and
498 * save the lowercase version of the non-escape
499 * character as the result. If there are other keys
500 * waiting, we have a true escape sequence, so
501 * interpret it. */
502 escapes = 0;
503 if (get_buffer_len() == 0) {
504 *meta_key = TRUE;
505 retval = tolower(*kbinput);
506 } else {
507 int *seq;
508 size_t seq_len;
509 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000510
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000511 /* Put back the non-escape character, get the
512 * complete escape sequence, translate the
513 * sequence into its corresponding key value,
514 * and save that as the result. */
515 unget_input(kbinput, 1);
516 seq_len = get_buffer_len();
517 seq = get_input(NULL, seq_len);
518 retval = get_escape_seq_kbinput(seq, seq_len,
519 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000520
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000521 /* If the escape sequence is unrecognized and
522 * not ignored, put back all of its characters
523 * except for the initial escape. */
524 if (retval == ERR && !ignore_seq)
525 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000526
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000527 free(seq);
528 }
529 break;
530 case 2:
531 /* Two escapes followed by one or more decimal
532 * digits: byte sequence mode. If the word
533 * sequence's range is limited to 2XX (the first
534 * digit is in the '0' to '2' range and it's the
535 * first digit, or it's in the '0' to '9' range and
536 * it's not the first digit), increment the byte
537 * sequence counter and interpret the digit. If the
538 * byte sequence's range is not limited to 2XX, fall
539 * through. */
540 if (('0' <= *kbinput && *kbinput <= '6' &&
541 byte_digits == 0) || ('0' <= *kbinput &&
542 *kbinput <= '9' && byte_digits > 0)) {
543 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000544
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000545 byte_digits++;
546 byte = get_byte_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000547#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000548 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000549#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000550 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000551
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000552 if (byte != ERR) {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +0000553 char *byte_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000554 int byte_mb_len, *seq, i;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000555
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000556 /* If we've read in a complete byte
557 * sequence, reset the byte sequence counter
558 * and the escape counter, and put back the
559 * corresponding byte value. */
560 byte_digits = 0;
561 escapes = 0;
562
563 /* Put back the multibyte equivalent of the
564 * byte value. */
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +0000565 byte_mb = make_mbchar(byte, &byte_mb_len);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000566
567 seq = (int *)nmalloc(byte_mb_len *
568 sizeof(int));
569
570 for (i = 0; i < byte_mb_len; i++)
571 seq[i] = (unsigned char)byte_mb[i];
572
573 unget_input(seq, byte_mb_len);
574
575 free(seq);
576 free(byte_mb);
577 }
578 } else {
579 /* Reset the escape counter. */
580 escapes = 0;
581 if (byte_digits == 0)
582 /* Two escapes followed by a non-decimal
583 * digit or a decimal digit that would
584 * create a byte sequence greater than 2XX,
585 * and we're not in the middle of a byte
586 * sequence: control character sequence
587 * mode. Interpret the control sequence and
588 * save the corresponding control character
589 * as the result. */
590 retval = get_control_kbinput(*kbinput);
591 else {
592 /* If we're in the middle of a byte
593 * sequence, reset the byte sequence counter
594 * and save the character we got as the
595 * result. */
596 byte_digits = 0;
597 retval = *kbinput;
598 }
599 }
600 break;
601 }
602 }
603
604 /* If we have a result and it's an extended keypad value (i.e, a
605 * value outside of byte range), set func_key to TRUE. */
606 if (retval != ERR)
607 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000608
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000609#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000610 fprintf(stderr, "parse_kbinput(): kbinput = %d, meta_key = %d, func_key = %d, escapes = %d, byte_digits = %d, retval = %d\n", *kbinput, (int)*meta_key, (int)*func_key, escapes, byte_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000611#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000612
613 /* Return the result. */
614 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000615}
616
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000617/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000618 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000619 * are generated when the keypad doesn't support the needed keys. If
620 * the escape sequence is recognized but we want to ignore it, return
621 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
622 * set ignore_seq to FALSE. Assume that Escape has already been read
623 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000624int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000625 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000626{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000627 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000628
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000629 *ignore_seq = FALSE;
630
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000631 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000632 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000633 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000634 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000635 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000636 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000637 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000638 case 'P': /* Esc O 2 P == F13 on
639 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000640 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000641 break;
642 case 'Q': /* Esc O 2 Q == F14 on
643 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000644 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000645 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000646 case 'R': /* Esc O 2 R == F15 on
647 * xterm. */
648 retval = KEY_F(15);
649 break;
650 case 'S': /* Esc O 2 S == F16 on
651 * xterm. */
652 retval = KEY_F(16);
653 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000654 }
655 }
656 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000657 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
658 case 'B': /* Esc O B == Down on
659 * VT100/VT320/xterm. */
660 case 'C': /* Esc O C == Right on
661 * VT100/VT320/xterm. */
662 case 'D': /* Esc O D == Left on
663 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000664 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000665 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000666 case 'E': /* Esc O E == Center (5) on numeric keypad
667 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000668 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000669 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000670 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000671 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000672 break;
673 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000674 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000675 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000676 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000677 * NumLock off on VT100/VT220/VT320/xterm/
678 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000679 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000680 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000681 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000682 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000683 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000684 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000685 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000686 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000687 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000688 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000689 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000690 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000691 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000692 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000693 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000694 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000695 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000696 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000697 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000698 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000699 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000700 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000701 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000702 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000703 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000704 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000705 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000706 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000707 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000708 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000709 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000710 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000711 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000712 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000713 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000714 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000715 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000716 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000717 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000718 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000719 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000720 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000721 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000722 * NumLock off on VT100/VT220/VT320/xterm/
723 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000724 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000725 break;
726 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000727 * NumLock off on VT100/VT220/VT320/xterm/
728 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000729 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000730 break;
731 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000732 * NumLock off on VT100/VT220/VT320/xterm/
733 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000734 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000735 break;
736 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000737 * NumLock off on VT100/VT220/VT320/xterm/
738 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000739 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000740 break;
741 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000742 * with NumLock off on VT100/VT220/VT320/
743 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000744 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000745 break;
746 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000747 * NumLock off on VT100/VT220/VT320/xterm/
748 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000749 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000750 break;
751 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000752 * with NumLock off on VT100/VT220/VT320/
753 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000754 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000755 break;
756 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000757 * with NumLock off on VT100/VT220/VT320/
758 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000759 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000760 break;
761 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000762 * with NumLock off on VT100/VT220/VT320/
763 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000764 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000765 break;
766 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000767 * keypad with NumLock off on VT100/VT220/
768 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000769 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000770 break;
771 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000772 * with NumLock off on VT100/VT220/VT320/
773 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000774 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000775 break;
776 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000777 * with NumLock off on VT100/VT220/VT320/
778 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000779 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000780 break;
781 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000782 * with NumLock off on VT100/VT220/VT320/
783 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000784 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000785 break;
786 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000787 * with NumLock off on VT100/VT220/VT320/
788 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000789 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000790 break;
791 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000792 * with NumLock off on VT100/VT220/VT320/
793 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000794 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000795 break;
796 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000797 * with NumLock off on VT100/VT220/VT320/
798 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000799 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000800 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000801 }
802 break;
803 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000804 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000805 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000806 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000807 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000808 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000809 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000810 break;
811 }
812 break;
813 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000814 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000815 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000816 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000817 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000818 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
819 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000820 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000821 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000822 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
823 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000824 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000825 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000826 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
827 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000828 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000829 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000830 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
831 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000832 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000833 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000834 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
835 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000836 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000837 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000838 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000839 * VT220/VT320/Linux console/
840 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000841 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000842 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000843 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000844 * VT220/VT320/Linux console/
845 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000846 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000847 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000848 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000849 * VT220/VT320/Linux console/
850 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000851 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000852 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000853 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000854 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000855 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000856 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000857 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000858 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000859 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
860 * xterm. */
861 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
862 * xterm. */
863 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
864 * xterm. */
865 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
866 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000867 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000868 break;
869 }
870 }
871 break;
872 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000873 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000874 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000875 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
876 * xterm. */
877 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
878 * xterm. */
879 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
880 * xterm. */
881 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
882 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000883 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000884 break;
885 }
886 }
887 break;
888 }
889 }
890 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000891 default: /* Esc [ 1 ~ == Home on
892 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000893 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000894 break;
895 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000896 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000897 break;
898 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000899 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000900 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000901 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000902 * VT220/VT320/Linux console/
903 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000904 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000905 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000906 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000907 * VT220/VT320/Linux console/
908 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000909 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000910 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000911 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000912 * VT220/VT320/Linux console/
913 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000914 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000915 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000916 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000917 * VT220/VT320/Linux console/
918 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000919 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000920 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000921 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000922 * VT220/VT320/Linux console/
923 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000924 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000925 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000926 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000927 * VT220/VT320/Linux console/
928 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000929 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000930 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000931 case '8': /* Esc [ 2 8 ~ == F15 on
932 * VT220/VT320/Linux console/
933 * rxvt/Eterm. */
934 retval = KEY_F(15);
935 break;
936 case '9': /* Esc [ 2 9 ~ == F16 on
937 * VT220/VT320/Linux console/
938 * rxvt/Eterm. */
939 retval = KEY_F(16);
940 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000941 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000942 * VT220/VT320/Linux console/
943 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000944 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000945 break;
946 }
947 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000948 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000949 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
950 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000951 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000952 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000953 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000954 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000955 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000956 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000957 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
958 * Linux console/xterm; Esc [ 5 ^ ==
959 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000960 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000961 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000962 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
963 * Linux console/xterm; Esc [ 6 ^ ==
964 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000965 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000966 break;
967 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000968 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000969 break;
970 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000971 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000972 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000973 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000974 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000975 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000976 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000977 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000978 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000979 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000980 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000981 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000982 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000983 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000984 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000985 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000986 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000987 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000988 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000989 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000990 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000991 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000992 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000993 case 'E': /* Esc [ E == Center (5) on numeric keypad
994 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000995 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000996 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000997 case 'F': /* Esc [ F == End on FreeBSD
998 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000999 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001000 break;
1001 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001002 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001003 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001004 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001005 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001006 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001007 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001008 break;
1009 case 'I': /* Esc [ I == PageUp on FreeBSD
1010 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001011 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001012 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001013 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001014 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001015 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001016 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001017 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001018 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001019 break;
1020 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001021 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001022 break;
1023 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001024 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001025 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001026 case 'P': /* Esc [ O P == F1 on
1027 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001028 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001029 break;
1030 case 'Q': /* Esc [ O Q == F2 on
1031 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001032 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001033 break;
1034 case 'R': /* Esc [ O R == F3 on
1035 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001036 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001037 break;
1038 case 'S': /* Esc [ O S == F4 on
1039 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001040 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001041 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001042 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001043 } else {
1044 /* Esc [ O == F3 on FreeBSD console. */
1045 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001046 }
1047 break;
1048 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001049 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001050 break;
1051 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001052 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001053 break;
1054 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001055 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001056 break;
1057 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001058 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001059 break;
1060 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001062 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001063 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001064 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001065 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001066 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001067 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001068 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001069 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001070 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001071 break;
1072 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001073 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001074 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001075 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001076 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001077 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001078 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001079 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001080 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001081 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001082 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001083 case 'c': /* Esc [ c == Shift-Right on rxvt/
1084 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001085 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001086 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001087 break;
1088 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001089 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001090 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001091 case 'A': /* Esc [ [ A == F1 on Linux
1092 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001093 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001094 break;
1095 case 'B': /* Esc [ [ B == F2 on Linux
1096 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001097 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001098 break;
1099 case 'C': /* Esc [ [ C == F3 on Linux
1100 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001101 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001102 break;
1103 case 'D': /* Esc [ [ D == F4 on Linux
1104 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001105 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001106 break;
1107 case 'E': /* Esc [ [ E == F5 on Linux
1108 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001109 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001110 break;
1111 }
1112 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001113 break;
1114 }
1115 break;
1116 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001117 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001118
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001119#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001120 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001121#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001122
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001123 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001124}
1125
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001126/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001127 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001128 * to many escape sequences. */
1129int get_escape_seq_abcd(int kbinput)
1130{
1131 switch (tolower(kbinput)) {
1132 case 'a':
1133 return NANO_PREVLINE_KEY;
1134 case 'b':
1135 return NANO_NEXTLINE_KEY;
1136 case 'c':
1137 return NANO_FORWARD_KEY;
1138 case 'd':
1139 return NANO_BACK_KEY;
1140 default:
1141 return ERR;
1142 }
1143}
1144
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001145/* Translate a byte sequence: turn a three-digit decimal number from
1146 * 000 to 255 into its corresponding byte value. */
1147int get_byte_kbinput(int kbinput
1148#ifndef NANO_SMALL
1149 , bool reset
1150#endif
1151 )
1152{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001153 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001154 int retval = ERR;
1155
1156#ifndef NANO_SMALL
1157 if (reset) {
1158 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001159 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001160 return ERR;
1161 }
1162#endif
1163
1164 /* Increment the byte digit counter. */
1165 byte_digits++;
1166
1167 switch (byte_digits) {
1168 case 1:
1169 /* One digit: reset the byte sequence holder and add the
1170 * digit we got to the 100's position of the byte sequence
1171 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001172 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001173 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001174 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001175 else
1176 /* If the character we got isn't a decimal digit, or if
1177 * it is and it would put the byte sequence out of byte
1178 * range, save it as the result. */
1179 retval = kbinput;
1180 break;
1181 case 2:
1182 /* Two digits: add the digit we got to the 10's position of
1183 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001184 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1185 '6' <= kbinput && kbinput <= '9'))
1186 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001187 else
1188 /* If the character we got isn't a decimal digit, or if
1189 * it is and it would put the byte sequence out of byte
1190 * range, save it as the result. */
1191 retval = kbinput;
1192 break;
1193 case 3:
1194 /* Three digits: add the digit we got to the 1's position of
1195 * the byte sequence holder, and save the corresponding word
1196 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001197 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1198 '6' <= kbinput && kbinput <= '9')) {
1199 byte += (kbinput - '0');
1200 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001201 } else
1202 /* If the character we got isn't a decimal digit, or if
1203 * it is and it would put the word sequence out of word
1204 * range, save it as the result. */
1205 retval = kbinput;
1206 break;
1207 default:
1208 /* More than three digits: save the character we got as the
1209 * result. */
1210 retval = kbinput;
1211 break;
1212 }
1213
1214 /* If we have a result, reset the byte digit counter and the byte
1215 * sequence holder. */
1216 if (retval != ERR) {
1217 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001218 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001219 }
1220
1221#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001222 fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte = %d, retval = %d\n", kbinput, byte_digits, byte, retval);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001223#endif
1224
1225 return retval;
1226}
1227
1228/* Translate a word sequence: turn a four-digit hexadecimal number from
1229 * 0000 to ffff (case-insensitive) into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001230int get_word_kbinput(int kbinput
1231#ifndef NANO_SMALL
1232 , bool reset
1233#endif
1234 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001235{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001236 static int word_digits = 0, word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001237 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001238
1239#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001240 if (reset) {
1241 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001242 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001243 return ERR;
1244 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001245#endif
1246
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001247 /* Increment the word digit counter. */
1248 word_digits++;
1249
1250 switch (word_digits) {
1251 case 1:
1252 /* One digit: reset the word sequence holder and add the
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001253 * digit we got to the 4096's position of the word sequence
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001254 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001255 word = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001256 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001257 word += (kbinput - '0') * 4096;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001258 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001259 word += (tolower(kbinput) + 10 - 'a') * 4096;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001260 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001261 /* If the character we got isn't a hexadecimal digit, or
1262 * if it is and it would put the word sequence out of
1263 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001264 retval = kbinput;
1265 break;
1266 case 2:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001267 /* Two digits: add the digit we got to the 256's position of
1268 * the word sequence holder. */
1269 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001270 word += (kbinput - '0') * 256;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001271 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001272 word += (tolower(kbinput) + 10 - 'a') * 256;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001273 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001274 /* If the character we got isn't a hexadecimal digit, or
1275 * if it is and it would put the word sequence out of
1276 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001277 retval = kbinput;
1278 break;
1279 case 3:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001280 /* Three digits: add the digit we got to the 16's position
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001281 * of the word sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001282 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001283 word += (kbinput - '0') * 16;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001284 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001285 word += (tolower(kbinput) + 10 - 'a') * 16;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001286 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001287 /* If the character we got isn't a hexadecimal digit, or
1288 * if it is and it would put the word sequence out of
1289 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001290 retval = kbinput;
1291 break;
1292 case 4:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001293 /* Four digits: add the digit we got to the 1's position of
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001294 * the word sequence holder, and save the corresponding word
1295 * value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001296 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001297 word += (kbinput - '0');
1298 retval = word;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001299 } else if ('a' <= tolower(kbinput) &&
1300 tolower(kbinput) <= 'f') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001301 word += (tolower(kbinput) + 10 - 'a');
1302 retval = word;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001303 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001304 /* If the character we got isn't a hexadecimal digit, or
1305 * if it is and it would put the word sequence out of
1306 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001307 retval = kbinput;
1308 break;
1309 default:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001310 /* More than four digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001311 * result. */
1312 retval = kbinput;
1313 break;
1314 }
1315
1316 /* If we have a result, reset the word digit counter and the word
1317 * sequence holder. */
1318 if (retval != ERR) {
1319 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001320 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001321 }
1322
1323#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001324 fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word = %d, retval = %d\n", kbinput, word_digits, word, retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001325#endif
1326
1327 return retval;
1328}
1329
1330/* Translate a control character sequence: turn an ASCII non-control
1331 * character into its corresponding control character. */
1332int get_control_kbinput(int kbinput)
1333{
1334 int retval;
1335
1336 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1337 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1338 kbinput == '`')
1339 retval = NANO_CONTROL_SPACE;
1340 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1341 else if ('3' <= kbinput && kbinput <= '7')
1342 retval = kbinput - 24;
1343 /* Ctrl-8 (Ctrl-?) */
1344 else if (kbinput == '8' || kbinput == '?')
1345 retval = NANO_CONTROL_8;
1346 /* Ctrl-A to Ctrl-_ */
1347 else if ('A' <= kbinput && kbinput <= '_')
1348 retval = kbinput - 64;
1349 /* Ctrl-a to Ctrl-~ */
1350 else if ('a' <= kbinput && kbinput <= '~')
1351 retval = kbinput - 96;
1352 else
1353 retval = kbinput;
1354
1355#ifdef DEBUG
1356 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1357#endif
1358
1359 return retval;
1360}
1361
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001362/* Put the output-formatted characters in output back into the default
1363 * keystroke buffer, so that they can be parsed and displayed as output
1364 * again. */
1365void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001366{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001367 int *input;
1368 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001369
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001370 if (output_len == 0)
1371 return;
1372
1373 input = (int *)nmalloc(output_len * sizeof(int));
1374 for (i = 0; i < output_len; i++)
1375 input[i] = (int)output[i];
1376 unget_input(input, output_len);
1377 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001378}
1379
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001380/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001381 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1382int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1383{
1384 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001385
1386 /* Turn off flow control characters if necessary so that we can type
1387 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001388 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001389 if (ISSET(PRESERVE))
1390 disable_flow_control();
1391 keypad(win, FALSE);
1392
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001393 /* Read in a stream of characters and interpret it if possible. */
1394 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001395
1396 /* Turn flow control characters back on if necessary and turn the
1397 * keypad back on now that we're done. */
1398 if (ISSET(PRESERVE))
1399 enable_flow_control();
1400 keypad(win, TRUE);
1401
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001402 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001403}
1404
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001405/* Read in a stream of all available characters, and return the length
1406 * of the string in kbinput_len. Translate the first few characters of
1407 * the input into the corresponding word value if possible. After that,
1408 * leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001409int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001410{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001411 int *kbinput, word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001412
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001413 /* Read in the first keystroke. */
1414 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001415
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001416 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001417 word = get_word_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001418#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001419 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001420#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001421 );
1422
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001423 /* If the first keystroke isn't a hexadecimal digit, put back the
1424 * first keystroke. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001425 if (word != ERR)
1426 unget_input(kbinput, 1);
1427 /* Otherwise, read in keystrokes until we have a complete word
1428 * sequence, and put back the corresponding word value. */
1429 else {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00001430 char *word_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001431 int word_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001432
1433 while (word == ERR) {
1434 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001435
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001436 word = get_word_kbinput(*kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001437#ifndef NANO_SMALL
1438 , FALSE
1439#endif
1440 );
1441 }
1442
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001443 /* Put back the multibyte equivalent of the word value. */
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00001444 word_mb = make_mbchar(word, &word_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001445
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001446 seq = (int *)nmalloc(word_mb_len * sizeof(int));
1447
1448 for (i = 0; i < word_mb_len; i++)
1449 seq[i] = (unsigned char)word_mb[i];
1450
1451 unget_input(seq, word_mb_len);
1452
1453 free(seq);
1454 free(word_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001455 }
1456
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001457 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001458 * result. */
1459 *kbinput_len = get_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001460 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001461
1462 return retval;
1463}
1464
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001465#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001466/* Check for a mouse event, and if one's taken place, save the
1467 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001468 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1469 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001470 * place on it, figure out which shortcut was clicked and put back the
1471 * equivalent keystroke(s). Return FALSE if no keystrokes were
1472 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001473 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001474bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001475{
1476 MEVENT mevent;
1477
1478 *mouse_x = -1;
1479 *mouse_y = -1;
1480
1481 /* First, get the actual mouse event. */
1482 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001483 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001484
1485 /* Save the screen coordinates where the mouse event took place. */
1486 *mouse_x = mevent.x;
1487 *mouse_y = mevent.y;
1488
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001489 /* If we're allowing shortcuts, the current shortcut list is being
1490 * displayed on the last two lines of the screen, and the mouse
1491 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001492 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001493 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1494 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001495 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001496 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001497 /* The number of shortcuts in the current shortcut list. */
1498 const shortcut *s = currshortcut;
1499 /* The actual shortcut we clicked on, starting at the first
1500 * one in the current shortcut list. */
1501
1502 /* Get the shortcut lists' length. */
1503 if (currshortcut == main_list)
1504 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001505 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001506 currslen = length_of_list(currshortcut);
1507
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001508 /* We don't show any more shortcuts than the main list
1509 * does. */
1510 if (currslen > MAIN_VISIBLE)
1511 currslen = MAIN_VISIBLE;
1512 }
1513
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001514 /* Calculate the width of each shortcut in the list (it's the
1515 * same for all of them). */
1516 if (currslen < 2)
1517 i = COLS / 6;
1518 else
1519 i = COLS / ((currslen / 2) + (currslen % 2));
1520
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001521 /* Calculate the y-coordinate relative to the beginning of
1522 * bottomwin. */
1523 j = *mouse_y - ((2 - no_more_space()) + 1) - editwinrows;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001524
1525 /* If we're on the statusbar, beyond the end of the shortcut
1526 * list, or beyond the end of a shortcut on the right side of
1527 * the screen, don't do anything. */
1528 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001529 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001530 j = (*mouse_x / i) * 2 + j;
1531 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001532 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001533
1534 /* Go through the shortcut list to determine which shortcut was
1535 * clicked. */
1536 for (; j > 0; j--)
1537 s = s->next;
1538
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001539 /* And put back the equivalent key. Assume that each shortcut
1540 * has, at the very least, an equivalent control key, an
1541 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001542 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001543 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001544 return TRUE;
1545 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001546 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001547 return TRUE;
1548 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001549 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001550 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001551}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001552#endif /* !DISABLE_MOUSE */
1553
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001554const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001555 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001556{
1557 const shortcut *s = s_list;
1558 size_t slen = length_of_list(s_list);
1559
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001560#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001561 fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %d, func_key = %d\n", *kbinput, (int)*meta_key, (int)*func_key);
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001562#endif
1563
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001564 /* Check for shortcuts. */
1565 for (; slen > 0; slen--) {
1566 /* We've found a shortcut if:
1567 *
1568 * 1. The key exists.
1569 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001570 * 3. meta_key is TRUE and the key is the primary or
1571 * miscellaneous meta sequence in the shortcut list.
1572 * 4. func_key is TRUE and the key is a function key in the
1573 * shortcut list. */
1574
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001575 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1576 (*meta_key == TRUE && (*kbinput == s->metaval ||
1577 *kbinput == s->miscval)) || (*func_key == TRUE &&
1578 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001579 break;
1580 }
1581
1582 s = s->next;
1583 }
1584
1585 /* Translate the shortcut to either its control key or its meta key
1586 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001587 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001588 if (slen > 0) {
1589 if (s->ctrlval != NANO_NO_KEY) {
1590 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001591 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001592 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001593 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001594 } else if (s->metaval != NANO_NO_KEY) {
1595 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001596 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001597 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001598 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001599 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001600 }
1601
1602 return NULL;
1603}
1604
1605#ifndef NANO_SMALL
1606const toggle *get_toggle(int kbinput, bool meta_key)
1607{
1608 const toggle *t = toggles;
1609
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001610#ifdef DEBUG
1611 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1612#endif
1613
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001614 /* Check for toggles. */
1615 for (; t != NULL; t = t->next) {
1616 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001617 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001618 if (meta_key && kbinput == t->val)
1619 break;
1620 }
1621
1622 return t;
1623}
1624#endif /* !NANO_SMALL */
1625
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001626int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001627 bool *ran_func, bool *finished, bool allow_funcs)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001628{
1629 int input;
1630 /* The character we read in. */
1631 static int *kbinput = NULL;
1632 /* The input buffer. */
1633 static size_t kbinput_len = 0;
1634 /* The length of the input buffer. */
1635 const shortcut *s;
1636 bool have_shortcut;
1637
1638 *s_or_t = FALSE;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001639 *ran_func = FALSE;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001640 *finished = FALSE;
1641
1642 /* Read in a character. */
1643 input = get_kbinput(bottomwin, meta_key, func_key);
1644
1645#ifndef DISABLE_MOUSE
1646 /* If we got a mouse click and it was on a shortcut, read in the
1647 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001648 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001649 if (do_mouse())
1650 input = get_kbinput(bottomwin, meta_key, func_key);
1651 else
1652 input = ERR;
1653 }
1654#endif
1655
1656 /* Check for a shortcut in the current list. */
1657 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1658
1659 /* If we got a shortcut from the current list, or a "universal"
1660 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1661 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1662 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1663 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1664 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001665 input == NANO_CUT_KEY ||
1666#ifndef NANO_SMALL
1667 input == NANO_NEXTWORD_KEY ||
1668#endif
1669 (*meta_key == TRUE && (
1670#ifndef NANO_SMALL
1671 input == NANO_PREVWORD_KEY ||
1672#endif
1673 input == NANO_VERBATIM_KEY)));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001674
1675 /* Set s_or_t to TRUE if we got a shortcut. */
1676 *s_or_t = have_shortcut;
1677
1678 if (allow_funcs) {
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001679 /* If we got a character, and it isn't a shortcut or toggle,
1680 * it's a normal text character. Display the warning if we're
1681 * in view mode, or add the character to the input buffer if
1682 * we're not. */
1683 if (input != ERR && *s_or_t == FALSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001684 /* If we're using restricted mode, the filename isn't blank,
1685 * and we're at the "Write File" prompt, disable text
1686 * input. */
1687 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1688 currshortcut != writefile_list) {
1689 kbinput_len++;
1690 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1691 sizeof(int));
1692 kbinput[kbinput_len - 1] = input;
1693 }
1694 }
1695
1696 /* If we got a shortcut, or if there aren't any other characters
1697 * waiting after the one we read in, we need to display all the
1698 * characters in the input buffer if it isn't empty. */
1699 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1700 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001701
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001702 /* Display all the characters in the input buffer at
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001703 * once, filtering out control characters. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001704 char *output = charalloc(kbinput_len + 1);
1705 size_t i;
1706 bool got_enter;
1707 /* Whether we got the Enter key. */
1708
1709 for (i = 0; i < kbinput_len; i++)
1710 output[i] = (char)kbinput[i];
1711 output[i] = '\0';
1712
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001713 do_statusbar_output(output, kbinput_len, &got_enter,
1714 FALSE);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001715
1716 free(output);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001717
1718 /* Empty the input buffer. */
1719 kbinput_len = 0;
1720 free(kbinput);
1721 kbinput = NULL;
1722 }
1723 }
1724
1725 if (have_shortcut) {
1726 switch (input) {
1727 /* Handle the "universal" statusbar prompt shortcuts. */
1728 case NANO_REFRESH_KEY:
1729 total_refresh();
1730 break;
1731 case NANO_HOME_KEY:
1732 do_statusbar_home();
1733 break;
1734 case NANO_END_KEY:
1735 do_statusbar_end();
1736 break;
1737 case NANO_FORWARD_KEY:
1738 do_statusbar_right();
1739 break;
1740 case NANO_BACK_KEY:
1741 do_statusbar_left();
1742 break;
1743 case NANO_BACKSPACE_KEY:
1744 /* If we're using restricted mode, the filename
1745 * isn't blank, and we're at the "Write File"
1746 * prompt, disable Backspace. */
1747 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1748 currshortcut != writefile_list)
1749 do_statusbar_backspace();
1750 break;
1751 case NANO_DELETE_KEY:
1752 /* If we're using restricted mode, the filename
1753 * isn't blank, and we're at the "Write File"
1754 * prompt, disable Delete. */
1755 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1756 currshortcut != writefile_list)
1757 do_statusbar_delete();
1758 break;
1759 case NANO_CUT_KEY:
1760 /* If we're using restricted mode, the filename
1761 * isn't blank, and we're at the "Write File"
1762 * prompt, disable Cut. */
1763 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1764 currshortcut != writefile_list)
1765 do_statusbar_cut_text();
1766 break;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001767#ifndef NANO_SMALL
1768 case NANO_NEXTWORD_KEY:
1769 do_statusbar_next_word();
1770 break;
1771 case NANO_PREVWORD_KEY:
1772 if (*meta_key == TRUE)
1773 do_statusbar_prev_word();
1774 break;
1775#endif
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001776 case NANO_VERBATIM_KEY:
1777 if (*meta_key == TRUE) {
1778 /* If we're using restricted mode, the filename
1779 * isn't blank, and we're at the "Write File"
1780 * prompt, disable verbatim input. */
1781 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001782 currshortcut != writefile_list) {
1783 bool got_enter;
1784 /* Whether we got the Enter key. */
1785
1786 do_statusbar_verbatim_input(&got_enter);
1787
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001788 /* If we got the Enter key, set input to the
1789 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001790 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001791 if (got_enter) {
1792 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001793 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001794 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001795 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001796 break;
1797 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001798 /* Handle the normal statusbar prompt shortcuts, setting
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001799 * ran_func to TRUE if we try to run their associated
1800 * functions and setting finished to TRUE to indicate
1801 * that we're done after trying to run their associated
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001802 * functions. */
1803 default:
1804 if (s->func != NULL) {
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001805 *ran_func = TRUE;
1806 if (!ISSET(VIEW_MODE) || s->viewok)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001807 s->func();
1808 }
1809 *finished = TRUE;
1810 }
1811 }
1812 }
1813
1814 return input;
1815}
1816
1817#ifndef DISABLE_MOUSE
1818bool do_statusbar_mouse(void)
1819{
1820 /* FIXME: If we clicked on a location in the statusbar, the cursor
1821 * should move to the location we clicked on. This functionality
1822 * should be in this function. */
1823 int mouse_x, mouse_y;
1824 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1825}
1826#endif
1827
1828void do_statusbar_home(void)
1829{
1830#ifndef NANO_SMALL
1831 if (ISSET(SMART_HOME)) {
1832 size_t statusbar_x_save = statusbar_x;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001833
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001834 statusbar_x = indent_length(answer);
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001835
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001836 if (statusbar_x == statusbar_x_save ||
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001837 statusbar_x == strlen(answer))
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001838 statusbar_x = 0;
1839 } else
1840#endif
1841 statusbar_x = 0;
1842}
1843
1844void do_statusbar_end(void)
1845{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001846 statusbar_x = strlen(answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001847}
1848
1849void do_statusbar_right(void)
1850{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001851 if (statusbar_x < strlen(answer))
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001852 statusbar_x = move_mbright(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001853}
1854
1855void do_statusbar_left(void)
1856{
1857 if (statusbar_x > 0)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001858 statusbar_x = move_mbleft(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001859}
1860
1861void do_statusbar_backspace(void)
1862{
1863 if (statusbar_x > 0) {
1864 do_statusbar_left();
1865 do_statusbar_delete();
1866 }
1867}
1868
1869void do_statusbar_delete(void)
1870{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001871 if (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001872 int char_buf_len = parse_mbchar(answer + statusbar_x, NULL,
1873 NULL, NULL);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001874 size_t line_len = strlen(answer + statusbar_x);
1875
1876 assert(statusbar_x < strlen(answer));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001877
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001878 charmove(answer + statusbar_x, answer + statusbar_x +
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001879 char_buf_len, strlen(answer) - statusbar_x -
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001880 char_buf_len + 1);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001881
1882 null_at(&answer, statusbar_x + line_len - char_buf_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001883 }
1884}
1885
1886void do_statusbar_cut_text(void)
1887{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001888 assert(answer != NULL);
1889
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001890#ifndef NANO_SMALL
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001891 if (ISSET(CUT_TO_END))
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001892 null_at(&answer, statusbar_x);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001893 else {
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001894#endif
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001895 null_at(&answer, 0);
1896 statusbar_x = 0;
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001897#ifndef NANO_SMALL
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001898 }
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001899#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001900}
1901
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001902#ifndef NANO_SMALL
1903void do_statusbar_next_word(void)
1904{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001905 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001906 int char_mb_len;
1907
1908 assert(answer != NULL);
1909
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001910 char_mb = charalloc(mb_cur_max());
1911
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001912 /* Move forward until we find the character after the last letter of
1913 * the current word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001914 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001915 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1916 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001917
1918 /* If we've found it, stop moving forward through the current
1919 * line. */
1920 if (!is_alnum_mbchar(char_mb))
1921 break;
1922
1923 statusbar_x += char_mb_len;
1924 }
1925
1926 /* Move forward until we find the first letter of the next word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001927 if (answer[statusbar_x] != '\0')
1928 statusbar_x += char_mb_len;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001929
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001930 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001931 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1932 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001933
1934 /* If we've found it, stop moving forward through the current
1935 * line. */
1936 if (is_alnum_mbchar(char_mb))
1937 break;
1938
1939 statusbar_x += char_mb_len;
1940 }
1941
1942 free(char_mb);
1943}
1944
1945void do_statusbar_prev_word(void)
1946{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001947 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001948 int char_mb_len;
1949 bool begin_line = FALSE;
1950
1951 assert(answer != NULL);
1952
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001953 char_mb = charalloc(mb_cur_max());
1954
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001955 /* Move backward until we find the character before the first letter
1956 * of the current word. */
1957 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001958 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1959 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001960
1961 /* If we've found it, stop moving backward through the current
1962 * line. */
1963 if (!is_alnum_mbchar(char_mb))
1964 break;
1965
1966 if (statusbar_x == 0)
1967 begin_line = TRUE;
1968 else
1969 statusbar_x = move_mbleft(answer, statusbar_x);
1970 }
1971
1972 /* Move backward until we find the last letter of the previous
1973 * word. */
1974 if (statusbar_x == 0)
1975 begin_line = TRUE;
1976 else
1977 statusbar_x = move_mbleft(answer, statusbar_x);
1978
1979 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001980 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1981 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001982
1983 /* If we've found it, stop moving backward through the current
1984 * line. */
1985 if (is_alnum_mbchar(char_mb))
1986 break;
1987
1988 if (statusbar_x == 0)
1989 begin_line = TRUE;
1990 else
1991 statusbar_x = move_mbleft(answer, statusbar_x);
1992 }
1993
1994 /* If we've found it, move backward until we find the character
1995 * before the first letter of the previous word. */
1996 if (!begin_line) {
1997 if (statusbar_x == 0)
1998 begin_line = TRUE;
1999 else
2000 statusbar_x = move_mbleft(answer, statusbar_x);
2001
2002 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002003 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
2004 NULL, NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002005
2006 /* If we've found it, stop moving backward through the
2007 * current line. */
2008 if (!is_alnum_mbchar(char_mb))
2009 break;
2010
2011 if (statusbar_x == 0)
2012 begin_line = TRUE;
2013 else
2014 statusbar_x = move_mbleft(answer, statusbar_x);
2015 }
2016
2017 /* If we've found it, move forward to the first letter of the
2018 * previous word. */
2019 if (!begin_line)
2020 statusbar_x += char_mb_len;
2021 }
2022
2023 free(char_mb);
2024}
2025#endif
2026
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002027void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002028{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002029 int *kbinput;
2030 size_t kbinput_len, i;
2031 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002032
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002033 *got_enter = FALSE;
2034
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002035 /* Read in all the verbatim characters. */
2036 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
2037
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002038 /* Display all the verbatim characters at once, not filtering out
2039 * control characters. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002040 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002041
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002042 for (i = 0; i < kbinput_len; i++)
2043 output[i] = (char)kbinput[i];
2044 output[i] = '\0';
2045
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002046 do_statusbar_output(output, kbinput_len, got_enter, TRUE);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002047
2048 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002049}
2050
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002051void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002052 *got_enter, bool allow_cntrls)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002053{
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002054 size_t answer_len, i = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002055 char *char_buf = charalloc(mb_cur_max());
2056 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002057
2058 assert(answer != NULL);
2059
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002060 answer_len = strlen(answer);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002061 *got_enter = FALSE;
2062
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002063 while (i < output_len) {
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002064 /* If allow_cntrls is FALSE, filter out nulls and newlines,
2065 * since they're control characters. */
2066 if (allow_cntrls) {
2067 /* Null to newline, if needed. */
2068 if (output[i] == '\0')
2069 output[i] = '\n';
2070 /* Newline to Enter, if needed. */
2071 else if (output[i] == '\n') {
2072 /* Set got_enter to TRUE to indicate that we got the
2073 * Enter key, put back the rest of the characters in
2074 * output so that they can be parsed and output again,
2075 * and get out. */
2076 *got_enter = TRUE;
2077 unparse_kbinput(output + i, output_len - i);
2078 return;
2079 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002080 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002081
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002082 /* Interpret the next multibyte character. If it's an invalid
2083 * multibyte character, interpret it as though it's a byte
2084 * character. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002085 char_buf_len = parse_mbchar(output + i, char_buf, NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002086
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002087 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002088
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002089 /* If allow_cntrls is FALSE, filter out a control character. */
2090 if (!allow_cntrls && is_cntrl_mbchar(output + i - char_buf_len))
2091 continue;
2092
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002093 /* More dangerousness fun =) */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002094 answer = charealloc(answer, answer_len + (char_buf_len * 2));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002095
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002096 assert(statusbar_x <= answer_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002097
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002098 charmove(&answer[statusbar_x + char_buf_len],
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002099 &answer[statusbar_x], answer_len - statusbar_x +
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002100 char_buf_len);
2101 charcpy(&answer[statusbar_x], char_buf, char_buf_len);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002102 answer_len += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002103
2104 do_statusbar_right();
2105 }
2106
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002107 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002108}
2109
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002110/* Return the placewewant associated with current_x, i.e, the zero-based
2111 * column position of the cursor. The value will be no smaller than
2112 * current_x. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002113size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002114{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002115 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002116}
2117
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002118/* actual_x() gives the index in str of the character displayed at
2119 * column xplus. That is, actual_x() is the largest value such that
2120 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2121size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002122{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002123 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002124 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002125 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002126 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002127
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002128 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002129
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002130 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002131 int str_len = parse_mbchar(str, NULL, NULL, &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002132
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002133 if (length > xplus)
2134 break;
2135
2136 i += str_len;
2137 str += str_len;
2138 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002139
Chris Allegretta6df90f52002-07-19 01:08:59 +00002140 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002141}
2142
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002143/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002144 * columns wide are the first size characters of str? */
2145size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002146{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002147 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002148 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002149
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002150 if (size == 0)
2151 return 0;
2152
2153 assert(str != NULL);
2154
2155 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002156 int str_len = parse_mbchar(str, NULL, NULL, &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002157
2158 str += str_len;
2159
2160 if (size <= str_len)
2161 break;
2162
2163 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002164 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002165
Chris Allegretta6df90f52002-07-19 01:08:59 +00002166 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002167}
2168
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002169/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002170size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002171{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002172 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002173}
2174
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002175void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002176{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002177 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002178}
2179
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002180void blank_topbar(void)
2181{
2182 if (!ISSET(MORE_SPACE))
2183 mvwaddstr(topwin, 1, 0, hblank);
2184}
2185
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002186void blank_edit(void)
2187{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002188 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002189 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002190 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002191}
2192
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002193void blank_statusbar(void)
2194{
2195 mvwaddstr(bottomwin, 0, 0, hblank);
2196}
2197
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002198void blank_bottombars(void)
2199{
2200 if (!ISSET(NO_HELP)) {
2201 mvwaddstr(bottomwin, 1, 0, hblank);
2202 mvwaddstr(bottomwin, 2, 0, hblank);
2203 }
2204}
2205
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002206void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002207{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002208 if (statusblank > 1)
2209 statusblank--;
2210 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
2211 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002212 blank_statusbar();
2213 wnoutrefresh(bottomwin);
2214 reset_cursor();
2215 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002216 }
2217}
2218
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002219/* Convert buf into a string that can be displayed on screen. The
2220 * caller wants to display buf starting with column start_col, and
2221 * extending for at most len columns. start_col is zero-based. len is
2222 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002223 * string is dynamically allocated, and should be freed. If dollars is
2224 * TRUE, the caller might put "$" at the beginning or end of the line if
2225 * it's too long. */
2226char *display_string(const char *buf, size_t start_col, size_t len, bool
2227 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002228{
2229 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002230 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002231 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002232 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002233 size_t alloc_len;
2234 /* The length of memory allocated for converted. */
2235 char *converted;
2236 /* The string we return. */
2237 size_t index;
2238 /* Current position in converted. */
2239
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002240 char *buf_mb = charalloc(mb_cur_max());
2241 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002242 bool bad_char;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002243
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002244 /* If dollars is TRUE, make room for the "$" at the end of the
2245 * line. */
2246 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2247 len--;
2248
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002249 if (len == 0)
2250 return mallocstrcpy(NULL, "");
2251
2252 start_index = actual_x(buf, start_col);
2253 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002254
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002255 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002256
David Lawrence Ramseyd29b9d52005-06-06 03:17:07 +00002257 /* Allocate enough space for the entire line, accounting for a
2258 * trailing multibyte character and/or tab. */
2259 alloc_len = (mb_cur_max() * (len + 1)) + tabsize;
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002260
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002261 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002262 index = 0;
2263
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002264 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002265 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002266 /* We don't display all of buf[start_index] since it starts to
2267 * the left of the screen. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002268 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL,
2269 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002270
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002271 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002272 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002273 char *ctrl_buf_mb = charalloc(mb_cur_max());
2274 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002275
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002276 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2277 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002278
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002279 for (i = 0; i < ctrl_buf_mb_len; i++)
2280 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002281
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002282 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002283
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002284 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002285
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002286 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002287 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002288 }
2289#ifdef NANO_WIDE
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002290 else if (mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002291 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002292 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002293
2294 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002295 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002296#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002297 }
2298
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002299 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseybc149412005-02-11 20:23:00 +00002300 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, &bad_char,
2301 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002302
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002303 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002304#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002305 if (ISSET(WHITESPACE_DISPLAY)) {
2306 int i;
2307
2308 for (i = 0; i < whitespace_len[0]; i++)
2309 converted[index++] = whitespace[i];
2310 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002311#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002312 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002313 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002314 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002315 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002316 start_col++;
2317 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002318 /* If buf contains a control character, interpret it. If it
2319 * contains an invalid multibyte control character, interpret
2320 * that character as though it's a normal control character. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002321 } else if (is_cntrl_mbchar(buf_mb)) {
2322 char *ctrl_buf_mb = charalloc(mb_cur_max());
2323 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002324
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002325 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002326 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002327
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002328 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2329 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002330
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002331 for (i = 0; i < ctrl_buf_mb_len; i++)
2332 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002333
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002334 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002335
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002336 free(ctrl_buf_mb);
2337 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002338#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002339 if (ISSET(WHITESPACE_DISPLAY)) {
2340 int i;
2341
2342 for (i = whitespace_len[0]; i < whitespace_len[0] +
2343 whitespace_len[1]; i++)
2344 converted[index++] = whitespace[i];
2345 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002346#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002347 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002348 start_col++;
2349 } else {
2350 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002351
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002352#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002353 /* If buf contains an invalid multibyte non-control
2354 * character, interpret that character as though it's a
2355 * normal non-control character. */
2356 if (!ISSET(NO_UTF8) && bad_char) {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002357 char *bad_buf_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002358 int bad_buf_mb_len;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002359
David Lawrence Ramsey4c6956b2005-01-12 04:32:43 +00002360 bad_buf_mb = make_mbchar((unsigned char)*buf_mb,
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002361 &bad_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002362
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002363 for (i = 0; i < bad_buf_mb_len; i++)
2364 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002365
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002366 start_col += mbwidth(bad_buf_mb);
2367
2368 free(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002369 } else {
2370#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002371 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002372 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002373
2374 start_col += mbwidth(buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002375#ifdef NANO_WIDE
2376 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002377#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002378 }
2379
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002380 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002381 }
2382
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002383 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002384 converted[index] = '\0';
2385
2386 /* Make sure converted takes up no more than len columns. */
2387 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002388 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002389
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002390 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002391}
2392
Chris Allegretta7662c862003-01-13 01:35:15 +00002393/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002394 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002395 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002396 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002397 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002398void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002399{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002400 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002401 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002402
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002403 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002404
Chris Allegrettab3655b42001-10-22 03:15:31 +00002405 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002406 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002407
Chris Allegretta6df90f52002-07-19 01:08:59 +00002408 mvwaddstr(bottomwin, 0, 0, buf);
2409 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002410
2411 if (COLS > 1)
2412 waddch(bottomwin, x_real < wid ? ' ' : '$');
2413 if (COLS > 2) {
2414 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002415 char *expanded = display_string(inputbuf, page_start, wid,
2416 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002417
2418 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002419 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002420
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002421 waddstr(bottomwin, expanded);
2422 free(expanded);
2423 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2424 } else
2425 wmove(bottomwin, 0, COLS - 1);
David Lawrence Ramseyd37f6a32005-03-26 20:41:36 +00002426
Chris Allegrettab3655b42001-10-22 03:15:31 +00002427 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002428}
2429
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002430/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002431 * statusq(). */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002432int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002433#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002434 filestruct **history_list,
Chris Allegretta5beed502003-01-05 20:41:21 +00002435#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002436 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002437#ifndef DISABLE_TABCOMP
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002438 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002439#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002440 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002441{
2442 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002443 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002444 size_t curranswer_len;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002445#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002446 bool tabbed = FALSE;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002447 /* Whether we've pressed Tab. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002448#endif
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002449#ifndef NANO_SMALL
2450 char *history = NULL;
2451 /* The current history string. */
2452 char *magichistory = NULL;
2453 /* The temporary string typed at the bottom of the history, if
2454 * any. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002455#ifndef DISABLE_TABCOMP
David Lawrence Ramseyd922f192005-06-02 19:50:18 +00002456 int last_kbinput = ERR;
2457 /* The key we pressed before the current key. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002458 size_t complete_len = 0;
2459 /* The length of the original string that we're trying to
2460 * tab complete, if any. */
2461#endif
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002462#endif /* !NANO_SMALL */
Chris Allegretta09fc4302003-01-16 22:16:38 +00002463
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002464 answer = mallocstrcpy(answer, curranswer);
David Lawrence Ramsey0e0fef02005-05-26 18:05:22 +00002465 curranswer_len = strlen(answer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002466
David Lawrence Ramsey045d1302005-05-26 05:27:19 +00002467 /* Only put statusbar_x at the end of the string if it's
2468 * uninitialized, if it would be past the end of curranswer, or if
2469 * resetstatuspos is TRUE. Otherwise, leave it alone. This is so
2470 * the cursor position stays at the same place if a prompt-changing
2471 * toggle is pressed. */
2472 if (statusbar_x == (size_t)-1 || statusbar_x > curranswer_len ||
2473 resetstatuspos)
2474 statusbar_x = curranswer_len;
2475
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002476 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002477
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002478 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002479
David Lawrence Ramsey10f880c2005-04-29 03:24:43 +00002480 /* Refresh the edit window and the statusbar before getting
2481 * input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002482 wnoutrefresh(edit);
2483 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002484
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002485 /* If we're using restricted mode, we aren't allowed to change the
2486 * name of a file once it has one because that would allow writing
2487 * to files not specified on the command line. In this case,
2488 * disable all keys that would change the text if the filename isn't
2489 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002490 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002491 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002492 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002493
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002494 assert(statusbar_x <= strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002495
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002496#ifndef DISABLE_TABCOMP
David Lawrence Ramsey22425a22005-04-16 15:57:19 +00002497 if (kbinput != NANO_TAB_KEY)
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002498 tabbed = FALSE;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002499#endif
Chris Allegretta04d848e2000-11-05 17:54:41 +00002500
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002501 switch (kbinput) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002502 case NANO_TAB_KEY:
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002503#ifndef DISABLE_TABCOMP
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002504#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002505 if (history_list != NULL) {
2506 if (last_kbinput != NANO_TAB_KEY)
2507 complete_len = strlen(answer);
2508
2509 if (complete_len > 0) {
2510 answer = mallocstrcpy(answer,
2511 get_history_completion(history_list,
2512 answer, complete_len));
2513 statusbar_x = strlen(answer);
2514 }
2515 } else
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002516#endif /* !NANO_SMALL */
David Lawrence Ramseye2ce2792005-05-26 05:33:57 +00002517 if (allow_tabs)
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002518 answer = input_tab(answer, &statusbar_x, &tabbed,
2519 list);
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002520#endif /* !DISABLE_TABCOMP */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002521 break;
2522 case NANO_PREVLINE_KEY:
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002523#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002524 if (history_list != NULL) {
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002525 /* If we're scrolling up at the bottom of the
2526 * history list, answer isn't blank, and
2527 * magichistory isn't set, save answer in
2528 * magichistory. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002529 if ((*history_list)->next == NULL &&
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002530 answer[0] != '\0' && magichistory == NULL)
2531 magichistory = mallocstrcpy(NULL, answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002532
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002533 /* Get the older search from the history list and
2534 * save it in answer. If there is no older search,
2535 * don't do anything. */
2536 if ((history =
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002537 get_history_older(history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002538 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002539 statusbar_x = strlen(answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002540 }
David Lawrence Ramsey75f4b7c2005-05-03 21:35:58 +00002541
2542 /* This key has a shortcut list entry when it's used
2543 * to move to an older search, which means that
2544 * finished has been set to TRUE. Set it back to
2545 * FALSE here, so that we aren't kicked out of the
2546 * statusbar prompt. */
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002547 finished = FALSE;
Chris Allegretta5beed502003-01-05 20:41:21 +00002548 }
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002549#endif /* !NANO_SMALL */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002550 break;
2551 case NANO_NEXTLINE_KEY:
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002552#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002553 if (history_list != NULL) {
2554 /* Get the newer search from the history list and
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002555 * save it in answer. If there is no newer search,
2556 * don't do anything. */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002557 if ((history =
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002558 get_history_newer(history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002559 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002560 statusbar_x = strlen(answer);
Chris Allegrettac30fc242003-08-11 00:32:45 +00002561 }
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002562
2563 /* If, after scrolling down, we're at the bottom of
2564 * the history list, answer is blank, and
2565 * magichistory is set, save magichistory in
2566 * answer. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002567 if ((*history_list)->next == NULL &&
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002568 answer[0] == '\0' && magichistory != NULL) {
2569 answer = mallocstrcpy(answer, magichistory);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002570 statusbar_x = strlen(answer);
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002571 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002572 }
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002573#endif /* !NANO_SMALL */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002574 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002575 }
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002576
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002577 /* If we have a shortcut with an associated function, break out
2578 * if we're finished after running or trying to run the
2579 * function. */
2580 if (finished)
2581 break;
2582
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002583#if !defined(NANO_SMALL) && !defined(DISABLE_TABCOMP)
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002584 last_kbinput = kbinput;
2585#endif
2586
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002587 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002588 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002589 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002590
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002591#ifndef NANO_SMALL
David Lawrence Ramsey8234f672005-06-02 02:32:39 +00002592 /* Free magichistory if we need to. */
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002593 if (magichistory != NULL)
2594 free(magichistory);
2595#endif
2596
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002597 /* We finished putting in an answer or ran a normal shortcut's
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002598 * associated function, so reset statusbar_x. */
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002599 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002600 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002601 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002602
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002603 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002604}
2605
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002606/* Ask a question on the statusbar. Answer will be stored in answer
2607 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002608 * otherwise, the valid shortcut key caught. curranswer is any editable
2609 * text that we want to put up by default.
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002610 *
David Lawrence Ramsey67e3b932005-05-23 18:49:28 +00002611 * The allow_tabs parameter indicates whether we should allow tabs to be
2612 * interpreted. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002613int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002614#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002615 filestruct **history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002616#endif
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002617 const char *msg, ...)
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002618{
2619 va_list ap;
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002620 char *foo = charalloc(((COLS - 4) * mb_cur_max()) + 1);
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002621 int retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002622#ifndef DISABLE_TABCOMP
2623 bool list = FALSE;
2624#endif
2625
2626 bottombars(s);
2627
2628 va_start(ap, msg);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002629 vsnprintf(foo, (COLS - 4) * mb_cur_max(), msg, ap);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002630 va_end(ap);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002631 null_at(&foo, actual_x(foo, COLS - 4));
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002632
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002633 retval = nanogetstr(allow_tabs, foo, curranswer,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002634#ifndef NANO_SMALL
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002635 history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002636#endif
2637 s
2638#ifndef DISABLE_TABCOMP
2639 , &list
2640#endif
2641 );
2642 free(foo);
2643 resetstatuspos = FALSE;
2644
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002645 switch (retval) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002646 case NANO_CANCEL_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002647 retval = -1;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002648 resetstatuspos = TRUE;
2649 break;
2650 case NANO_ENTER_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002651 retval = (answer[0] == '\0') ? -2 : 0;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002652 resetstatuspos = TRUE;
2653 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002654 }
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002655
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002656 blank_statusbar();
2657
2658#ifdef DEBUG
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002659 fprintf(stderr, "answer = \"%s\"\n", answer);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002660#endif
2661
2662#ifndef DISABLE_TABCOMP
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002663 /* If we've done tab completion, there might be a list of
2664 * filename matches on the edit window at this point. Make sure
2665 * that they're cleared off. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002666 if (list)
2667 edit_refresh();
2668#endif
2669
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002670 return retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002671}
2672
2673void statusq_abort(void)
2674{
2675 resetstatuspos = TRUE;
2676}
2677
Chris Allegrettaf717f982003-02-13 22:25:01 +00002678void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002679{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002680 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002681 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002682 size_t verlen = strlenpt(VERMSG) + 1;
2683 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002684 const char *prefix;
2685 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2686 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002687 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002688 const char *state;
2689 /* "Modified", "View", or spaces the length of "Modified".
2690 * Tells the state of this buffer. */
2691 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002692 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002693 char *exppath = NULL;
2694 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002695 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002696 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002697 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002698 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002699
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002700 assert(path != NULL || filename != NULL);
2701 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002702
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002703 wattron(topwin, A_REVERSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002704 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002705
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002706 if (COLS <= 5 || COLS - 5 < verlen)
2707 space = 0;
2708 else {
2709 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002710 /* Reserve 2/3 of the screen plus one column for after the
2711 * version message. */
2712 if (space < COLS - (COLS / 3) + 1)
2713 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002714 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002715
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002716 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002717 /* The version message should only take up 1/3 of the screen
2718 * minus one column. */
2719 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002720 waddstr(topwin, " ");
2721 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002722
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002723 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002724 state = _("Modified");
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002725 else if (ISSET(VIEW_MODE))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002726 state = _("View");
2727 else {
2728 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002729 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002730 state = &hblank[COLS - statelen];
2731 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002732 statelen = strnlenpt(state, COLS);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002733
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002734 /* We need a space before state. */
2735 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2736 statelen++;
2737
2738 assert(space >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002739
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002740 if (space == 0 || statelen >= space)
2741 goto the_end;
2742
2743#ifndef DISABLE_BROWSER
2744 if (path != NULL)
2745 prefix = _("DIR:");
2746 else
2747#endif
2748 if (filename[0] == '\0') {
2749 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002750 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002751 } else
2752 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002753
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002754 assert(statelen < space);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002755
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002756 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002757
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002758 /* If newfie is FALSE, we need a space after prefix. */
2759 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002760 prefixlen++;
2761
2762 if (path == NULL)
2763 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002764 if (space >= prefixlen + statelen)
2765 space -= prefixlen + statelen;
2766 else
2767 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002768 /* space is now the room we have for the file name. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002769
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002770 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002771 size_t lenpt = strlenpt(path), start_col;
2772
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002773 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002774
2775 if (dots) {
2776 start_col = lenpt - space + 3;
2777 space -= 3;
2778 } else
2779 start_col = 0;
2780
2781 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002782 }
2783
2784 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002785 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2786 /* The length of the expanded filename. */
2787
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002788 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002789 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002790 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002791 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002792 assert(strlenpt(prefix) + 1 == prefixlen);
2793
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002794 waddch(topwin, ' ');
2795 waddstr(topwin, exppath);
2796 }
2797 } else {
2798 /* We will say something like "File: ...ename". */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002799 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002800 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002801 goto the_end;
2802 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002803 waddnstr(topwin, "...", space + 3);
2804 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002805 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002806 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002807 }
2808
2809 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002810 free(exppath);
2811
2812 if (COLS <= 1 || statelen >= COLS - 1)
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002813 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002814 else {
2815 assert(COLS - statelen - 2 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002816
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002817 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002818 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
2819 actual_x(state, statelen));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002820 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002821
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002822 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002823
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002824 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002825 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002826 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002827}
2828
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002829/* If modified is not already set, set it and update titlebar. */
2830void set_modified(void)
2831{
2832 if (!ISSET(MODIFIED)) {
2833 SET(MODIFIED);
2834 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002835 }
2836}
2837
2838void statusbar(const char *msg, ...)
2839{
2840 va_list ap;
2841
2842 va_start(ap, msg);
2843
2844 /* Curses mode is turned off. If we use wmove() now, it will muck
2845 * up the terminal settings. So we just use vfprintf(). */
2846 if (curses_ended) {
2847 vfprintf(stderr, msg, ap);
2848 va_end(ap);
2849 return;
2850 }
2851
2852 /* Blank out the line. */
2853 blank_statusbar();
2854
2855 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002856 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002857 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002858#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002859 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002860
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002861 UNSET(WHITESPACE_DISPLAY);
2862#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002863 bar = charalloc(mb_cur_max() * (COLS - 3));
2864 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002865 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002866 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002867#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2868 if (old_whitespace)
2869 SET(WHITESPACE_DISPLAY);
2870#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002871 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002872 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002873 start_x = (COLS - foo_len - 4) / 2;
2874
2875 wmove(bottomwin, 0, start_x);
2876 wattron(bottomwin, A_REVERSE);
2877
2878 waddstr(bottomwin, "[ ");
2879 waddstr(bottomwin, foo);
2880 free(foo);
2881 waddstr(bottomwin, " ]");
2882 wattroff(bottomwin, A_REVERSE);
2883 wnoutrefresh(bottomwin);
2884 reset_cursor();
2885 wrefresh(edit);
2886 /* Leave the cursor at its position in the edit window, not
2887 * in the statusbar. */
2888 }
2889
2890 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002891 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002892}
2893
Chris Allegretta6232d662002-05-12 19:52:15 +00002894void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002895{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002896 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002897
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002898 if (ISSET(NO_HELP))
2899 return;
2900
Chris Allegretta6232d662002-05-12 19:52:15 +00002901 if (s == main_list) {
2902 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002903
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002904 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002905 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002906 slen = length_of_list(s);
2907
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002908 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002909 if (slen > MAIN_VISIBLE)
2910 slen = MAIN_VISIBLE;
2911 }
2912
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002913 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002914 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002915 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002916
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002917 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002918
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002919 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002920 const char *keystr;
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002921 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002922
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002923 /* Yucky sentinel values that we can't handle a better way. */
2924 if (s->ctrlval == NANO_CONTROL_SPACE)
2925 strcpy(foo, "^ ");
2926 else if (s->ctrlval == NANO_CONTROL_8)
2927 strcpy(foo, "^?");
2928 /* Normal values. Assume that the shortcut has an equivalent
2929 * control key, meta key sequence, or both. */
2930 else if (s->ctrlval != NANO_NO_KEY)
2931 sprintf(foo, "^%c", s->ctrlval + 64);
2932 else if (s->metaval != NANO_NO_KEY)
2933 sprintf(foo, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00002934
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002935 keystr = foo;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002936
2937 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002938 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002939 }
2940
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002941 wnoutrefresh(bottomwin);
2942 reset_cursor();
2943 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002944}
2945
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002946/* Write a shortcut key to the help area at the bottom of the window.
2947 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2948 * to write at most len characters, even if len is very small and
2949 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2950 * the whole string! We do not bother padding the entry with blanks. */
2951void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002952{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002953 size_t keystroke_len = strlenpt(keystroke) + 1;
2954
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002955 assert(keystroke != NULL && desc != NULL);
2956
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002957 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002958 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002959 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002960
2961 if (len > keystroke_len)
2962 len -= keystroke_len;
2963 else
2964 len = 0;
2965
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002966 if (len > 0) {
2967 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002968 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002969 }
2970}
2971
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002972/* nano scrolls horizontally within a line in chunks. This function
2973 * returns the column number of the first character displayed in the
2974 * window when the cursor is at the given column. Note that
2975 * 0 <= column - get_page_start(column) < COLS. */
2976size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002977{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002978 assert(COLS > 0);
2979 if (column == 0 || column < COLS - 1)
2980 return 0;
2981 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002982 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002983 else if (COLS > 2)
2984 return column - (COLS - 2);
2985 else
2986 return column - (COLS - 1);
2987 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002988}
2989
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002990/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002991 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002992void reset_cursor(void)
2993{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002994 /* If we haven't opened any files yet, put the cursor in the top
2995 * left corner of the edit window and get out. */
2996 if (edittop == NULL || current == NULL) {
2997 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002998 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002999 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003000
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003001 current_y = current->lineno - edittop->lineno;
3002 if (current_y < editwinrows) {
3003 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003004 wmove(edit, current_y, x - get_page_start(x));
3005 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003006}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003007
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003008/* edit_add() takes care of the job of actually painting a line into the
3009 * edit window. fileptr is the line to be painted, at row yval of the
3010 * window. converted is the actual string to be written to the window,
3011 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003012 * characters. start is the column number of the first character of
3013 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003014 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003015void edit_add(const filestruct *fileptr, const char *converted, int
3016 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003017{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003018#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003019 size_t startpos = actual_x(fileptr->data, start);
3020 /* The position in fileptr->data of the leftmost character
3021 * that displays at least partially on the window. */
3022 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3023 /* The position in fileptr->data of the first character that is
3024 * completely off the window to the right.
3025 *
3026 * Note that endpos might be beyond the null terminator of the
3027 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003028#endif
3029
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003030 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003031 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003032
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003033 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003034 * just the text that needs it). */
3035 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003036
Chris Allegretta7dd77682001-12-08 19:52:28 +00003037#ifdef ENABLE_COLOR
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003038 if (colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003039 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003040
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003041 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3042 int x_start;
3043 /* Starting column for mvwaddnstr. Zero-based. */
3044 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003045 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003046 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003047 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003048 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003049 regmatch_t startmatch; /* match position for start_regexp */
3050 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003051
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003052 if (tmpcolor->bright)
3053 wattron(edit, A_BOLD);
3054 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003055 /* Two notes about regexec(). Return value 0 means there is
3056 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003057 * after the match. */
3058
3059 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003060 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003061 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003062
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003063 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003064 * last match. Even though two matches may overlap, we
3065 * want to ignore them, so that we can highlight
3066 * C-strings correctly. */
3067 while (k < endpos) {
3068 /* Note the fifth parameter to regexec(). It says
3069 * not to match the beginning-of-line character
3070 * unless k is 0. If regexec() returns REG_NOMATCH,
3071 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003072 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003073 &startmatch, (k == 0) ? 0 :
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003074 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003075 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003076 /* Translate the match to the beginning of the
3077 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003078 startmatch.rm_so += k;
3079 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003080 if (startmatch.rm_so == startmatch.rm_eo) {
3081 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003082 statusbar(
3083 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003084 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003085 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003086 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003087 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003088 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003089 x_start = strnlenpt(fileptr->data,
3090 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003091
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003092 index = actual_x(converted, x_start);
3093
3094 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003095 strnlenpt(fileptr->data,
3096 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003097
3098 assert(0 <= x_start && 0 <= paintlen);
3099
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003100 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003101 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003102 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003103 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003104 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003105 } else {
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003106 /* This is a multi-line regexp. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003107 * First, we have to see if the beginning of the line is
3108 * colored by a start on an earlier line, and an end on
3109 * this line or later.
3110 *
3111 * We find the first line before fileptr matching the
3112 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003113 * end, then go to step two. Otherwise, find the next
3114 * line after start_line matching the end. If that line
3115 * is not before fileptr, then paint the beginning of
3116 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003117 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003118 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003119 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003120 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003121 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003122
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003123 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003124 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003125 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003126 /* If there is an end on this line, there is no need
3127 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003128 if (regexec(tmpcolor->end, start_line->data, 0,
3129 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003130 goto step_two;
3131 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003132 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003133 /* No start found, so skip to the next step. */
3134 if (start_line == NULL)
3135 goto step_two;
3136 /* Now start_line is the first line before fileptr
3137 * containing a start match. Is there a start on this
3138 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003139 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003140 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003141 start_col += startmatch.rm_so;
3142 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003143 if (regexec(tmpcolor->end, start_line->data +
3144 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003145 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003146 REG_NOTBOL) == REG_NOMATCH)
3147 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003148 break;
3149 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003150 if (regexec(&tmpcolor->start, start_line->data +
3151 start_col, 1, &startmatch,
3152 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003153 /* No later start on this line. */
3154 goto step_two;
3155 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003156 /* Indeed, there is a start not followed on this line by
3157 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003158
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003159 /* We have already checked that there is no end before
3160 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003161 * the start at all? We don't paint unterminated
3162 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003163 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003164 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003165 regexec(tmpcolor->end, end_line->data, 1,
3166 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003167 end_line = end_line->next;
3168
3169 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003170 if (end_line == NULL || (end_line == fileptr &&
3171 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003172 goto step_two;
3173
3174 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003175 if (end_line != fileptr)
3176 /* If the start of fileptr is on a different line
3177 * from the end, paintlen is -1, meaning that
3178 * everything on the line gets painted. */
3179 paintlen = -1;
3180 else
3181 /* Otherwise, paintlen is the expanded location of
3182 * the end of the match minus the expanded location
3183 * of the beginning of the page. */
3184 paintlen = actual_x(converted,
3185 strnlenpt(fileptr->data, endmatch.rm_eo) -
3186 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003187
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003188 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003189
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003190 step_two:
3191 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003192 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003193
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003194 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003195 if (regexec(&tmpcolor->start,
3196 fileptr->data + start_col, 1, &startmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003197 (start_col == 0) ? 0 :
3198 REG_NOTBOL) == REG_NOMATCH ||
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003199 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003200 /* No more starts on this line. */
3201 break;
3202 /* Translate the match to be relative to the
3203 * beginning of the line. */
3204 startmatch.rm_so += start_col;
3205 startmatch.rm_eo += start_col;
3206
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003207 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003208 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003209 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003210 x_start = strnlenpt(fileptr->data,
3211 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003212
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003213 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003214
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003215 if (regexec(tmpcolor->end,
3216 fileptr->data + startmatch.rm_eo, 1, &endmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003217 (startmatch.rm_eo == 0) ? 0 :
3218 REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003219 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003220 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003221 endmatch.rm_so += startmatch.rm_eo;
3222 endmatch.rm_eo += startmatch.rm_eo;
3223 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003224 * appear on this page, and is the match more
3225 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003226 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003227 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003228 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003229 strnlenpt(fileptr->data,
3230 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003231
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003232 assert(0 <= x_start && x_start < COLS);
3233
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003234 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003235 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003236 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003237 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003238 /* There is no end on this line. But we haven't
3239 * yet looked for one on later lines. */
3240 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003241
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003242 while (end_line != NULL &&
3243 regexec(tmpcolor->end, end_line->data,
3244 0, NULL, 0) == REG_NOMATCH)
3245 end_line = end_line->next;
3246
3247 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003248 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003249
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003250 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003251 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003252 /* We painted to the end of the line, so
3253 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003254 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003255 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003256 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003257 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003258 }
3259 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003260
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003261 wattroff(edit, A_BOLD);
3262 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003263 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003264 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003265#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003266
Chris Allegretta7dd77682001-12-08 19:52:28 +00003267#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003268 if (ISSET(MARK_ISSET)
3269 && (fileptr->lineno <= mark_beginbuf->lineno
3270 || fileptr->lineno <= current->lineno)
3271 && (fileptr->lineno >= mark_beginbuf->lineno
3272 || fileptr->lineno >= current->lineno)) {
3273 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003274
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003275 const filestruct *top;
3276 /* Either current or mark_beginbuf, whichever is first. */
3277 size_t top_x;
3278 /* current_x or mark_beginx, corresponding to top. */
3279 const filestruct *bot;
3280 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003281 int x_start;
3282 /* Starting column for mvwaddnstr. Zero-based. */
3283 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003284 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003285 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003286 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003287 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003288
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003289 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003290
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003291 if (top->lineno < fileptr->lineno || top_x < startpos)
3292 top_x = startpos;
3293 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3294 bot_x = endpos;
3295
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003296 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003297 if (top_x < endpos && bot_x > startpos) {
3298 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003299
3300 /* x_start is the expanded location of the beginning of the
3301 * mark minus the beginning of the page. */
3302 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003303
3304 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003305 /* If the end of the mark is off the page, paintlen is
3306 * -1, meaning that everything on the line gets
3307 * painted. */
3308 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003309 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003310 /* Otherwise, paintlen is the expanded location of the
3311 * end of the mark minus the expanded location of the
3312 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003313 paintlen = strnlenpt(fileptr->data, bot_x) -
3314 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003315
3316 /* If x_start is before the beginning of the page, shift
3317 * paintlen x_start characters to compensate, and put
3318 * x_start at the beginning of the page. */
3319 if (x_start < 0) {
3320 paintlen += x_start;
3321 x_start = 0;
3322 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003323
3324 assert(x_start >= 0 && x_start <= strlen(converted));
3325
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003326 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003327
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003328 if (paintlen > 0)
3329 paintlen = actual_x(converted + index, paintlen);
3330
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003331 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003332 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003333 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003334 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003335 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003336 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003337#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003338}
3339
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003340/* Just update one line in the edit buffer. This is basically a wrapper
3341 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003342 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003343 * If fileptr != current, then index is considered 0. The line will be
3344 * displayed starting with fileptr->data[index]. Likely args are
3345 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003346void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003347{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003348 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003349 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003350 char *converted;
3351 /* fileptr->data converted to have tabs and control characters
3352 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003353 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003354
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003355 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003356
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003357 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003358
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003359 /* We assume the line numbers are valid. Is that really true? */
3360 assert(line < 0 || line == check_linenumbers(fileptr));
3361
3362 if (line < 0 || line >= editwinrows)
3363 return;
3364
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003365 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003366 mvwaddstr(edit, line, 0, hblank);
3367
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003368 /* Next, convert variables that index the line to their equivalent
3369 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003370 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003371 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003372
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003373 /* Expand the line, replacing tabs with spaces, and control
3374 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003375 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003376
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003377 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003378 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003379 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003380
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003381 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003382 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003383 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003384 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003385}
3386
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003387/* Return a nonzero value if we need an update after moving
3388 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003389 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003390int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003391{
3392 return
3393#ifndef NANO_SMALL
3394 ISSET(MARK_ISSET) ||
3395#endif
3396 get_page_start(old_pww) != get_page_start(placewewant);
3397}
3398
3399/* Return a nonzero value if we need an update after moving vertically.
3400 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003401 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003402int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003403{
3404 return
3405#ifndef NANO_SMALL
3406 ISSET(MARK_ISSET) ||
3407#endif
3408 get_page_start(old_pww) != get_page_start(placewewant);
3409}
3410
3411/* Scroll the edit window in the given direction and the given number
3412 * of lines, and draw new lines on the blank lines left after the
3413 * scrolling. direction is the direction to scroll, either UP or DOWN,
3414 * and nlines is the number of lines to scroll. Don't redraw the old
3415 * topmost or bottommost line (where we assume current is) before
3416 * scrolling or draw the new topmost or bottommost line after scrolling
3417 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003418 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003419void edit_scroll(updown direction, int nlines)
3420{
3421 filestruct *foo;
3422 int i, scroll_rows = 0;
3423
3424 /* Scrolling less than one line or more than editwinrows lines is
3425 * redundant, so don't allow it. */
3426 if (nlines < 1 || nlines > editwinrows)
3427 return;
3428
3429 /* Move the top line of the edit window up or down (depending on the
3430 * value of direction) nlines lines. If there are fewer lines of
3431 * text than that left, move it to the top or bottom line of the
3432 * file (depending on the value of direction). Keep track of
3433 * how many lines we moved in scroll_rows. */
3434 for (i = nlines; i > 0; i--) {
3435 if (direction == UP) {
3436 if (edittop->prev == NULL)
3437 break;
3438 edittop = edittop->prev;
3439 scroll_rows--;
3440 } else {
3441 if (edittop->next == NULL)
3442 break;
3443 edittop = edittop->next;
3444 scroll_rows++;
3445 }
3446 }
3447
3448 /* Scroll the text on the screen up or down scroll_rows lines,
3449 * depending on the value of direction. */
3450 scrollok(edit, TRUE);
3451 wscrl(edit, scroll_rows);
3452 scrollok(edit, FALSE);
3453
3454 foo = edittop;
3455 if (direction != UP) {
3456 int slines = editwinrows - nlines;
3457 for (; slines > 0 && foo != NULL; slines--)
3458 foo = foo->next;
3459 }
3460
3461 /* And draw new lines on the blank top or bottom lines of the edit
3462 * window, depending on the value of direction. Don't draw the new
3463 * topmost or new bottommost line. */
3464 while (scroll_rows != 0 && foo != NULL) {
3465 if (foo->next != NULL)
3466 update_line(foo, 0);
3467 if (direction == UP)
3468 scroll_rows++;
3469 else
3470 scroll_rows--;
3471 foo = foo->next;
3472 }
3473}
3474
3475/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003476 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003477void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003478{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003479 int do_refresh = need_vertical_update(0) ||
3480 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003481 const filestruct *foo;
3482
3483 /* If either old_current or current is offscreen, refresh the screen
3484 * and get out. */
3485 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3486 edittop->lineno + editwinrows || current->lineno <
3487 edittop->lineno || current->lineno >= edittop->lineno +
3488 editwinrows) {
3489 edit_refresh();
3490 return;
3491 }
3492
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003493 /* Update old_current and current if we're not on the first page
3494 * and/or we're not on the same page as before. If the mark is on,
3495 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003496 foo = old_current;
3497 while (foo != current) {
3498 if (do_refresh)
3499 update_line(foo, 0);
3500#ifndef NANO_SMALL
3501 if (!ISSET(MARK_ISSET))
3502#endif
3503 break;
3504 if (foo->lineno > current->lineno)
3505 foo = foo->prev;
3506 else
3507 foo = foo->next;
3508 }
3509 if (do_refresh)
3510 update_line(current, current_x);
3511}
3512
Chris Allegretta6df90f52002-07-19 01:08:59 +00003513/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003514void edit_refresh(void)
3515{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003516 if (current->lineno < edittop->lineno ||
3517 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003518 /* Note that edit_update() changes edittop so that it's in range
3519 * of current. Thus, when it then calls edit_refresh(), there
3520 * is no danger of getting an infinite loop. */
3521 edit_update(
3522#ifndef NANO_SMALL
3523 ISSET(SMOOTHSCROLL) ? NONE :
3524#endif
3525 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003526 else {
3527 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003528 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003529
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003530#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003531 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003532#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003533
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003534 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003535 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003536 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003537 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003538 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003539 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003540 }
3541 while (nlines < editwinrows) {
3542 mvwaddstr(edit, nlines, 0, hblank);
3543 nlines++;
3544 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003545 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003546 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003547 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003548}
3549
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003550/* A nice generic routine to update the edit buffer. We keep current in
3551 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003552void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003553{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003554 filestruct *foo = current;
3555
Chris Allegretta6df90f52002-07-19 01:08:59 +00003556 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003557 /* If location is CENTER, we move edittop up (editwinrows / 2)
3558 * lines. This puts current at the center of the screen. If
3559 * location is NONE, we move edittop up current_y lines if
3560 * current_y is in range of the screen, 0 lines if current_y is
3561 * less than 0, or (editwinrows - 1) lines if current_y is
3562 * greater than (editwinrows - 1). This puts current at the
3563 * same place on the screen as before, or at the top or bottom
3564 * of the screen if edittop is beyond either. */
3565 int goal;
3566
3567 if (location == CENTER)
3568 goal = editwinrows / 2;
3569 else {
3570 goal = current_y;
3571
3572 /* Limit goal to (editwinrows - 1) lines maximum. */
3573 if (goal > editwinrows - 1)
3574 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003575 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003576
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003577 for (; goal > 0 && foo->prev != NULL; goal--)
3578 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003579 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003580
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003581 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003582 edit_refresh();
3583}
3584
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003585/* Ask a simple yes/no question, specified in msg, on the statusbar.
3586 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3587 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003588int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003589{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003590 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003591 const char *yesstr; /* String of yes characters accepted. */
3592 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003593 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003594
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003595 /* yesstr, nostr, and allstr are strings of any length. Each string
David Lawrence Ramseydcb4e3a2005-04-08 20:27:02 +00003596 * consists of all single-byte characters accepted as valid
3597 * characters for that value. The first value will be the one
3598 * displayed in the shortcuts. Translators: if possible, specify
3599 * both the shortcuts for your language and English. For example,
3600 * in French: "OoYy" for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003601 yesstr = _("Yy");
3602 nostr = _("Nn");
3603 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003604
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003605 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003606 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003607
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003608 if (COLS < 32)
3609 width = COLS / 2;
3610
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003611 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003612 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003613
Chris Allegretta6232d662002-05-12 19:52:15 +00003614 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003615 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003616 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003617
3618 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003619 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003620 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003621 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003622 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003623
Chris Allegrettadb28e962003-01-28 01:23:40 +00003624 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003625 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003626 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003627
Chris Allegrettadb28e962003-01-28 01:23:40 +00003628 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003629 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003630 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003631
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003632 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003633
3634 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003635 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003636
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003637 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003638
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003639 wrefresh(bottomwin);
3640
Chris Allegrettadb28e962003-01-28 01:23:40 +00003641 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003642 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003643 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003644#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003645 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003646#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003647
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003648 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003649
David Lawrence Ramseyda331532005-06-06 17:00:08 +00003650 if (kbinput == NANO_REFRESH_KEY) {
3651 total_update();
3652 continue;
3653 } else if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003654 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003655#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003656 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003657 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003658
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003659 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003660 wenclose(bottomwin, mouse_y, mouse_x) &&
3661 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003662 int x = mouse_x / width;
3663 /* Did we click in the first column of shortcuts, or
3664 * the second? */
3665 int y = mouse_y - editwinrows - 3;
3666 /* Did we click in the first row of shortcuts? */
3667
3668 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3669
3670 /* x = 0 means they clicked Yes or No.
3671 * y = 0 means Yes or All. */
3672 ok = -2 * x * y + x - y + 1;
3673
3674 if (ok == 2 && !all)
3675 ok = -2;
3676 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003677 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003678#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003679 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003680 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003681 else if (strchr(yesstr, kbinput) != NULL)
3682 ok = 1;
3683 else if (strchr(nostr, kbinput) != NULL)
3684 ok = 0;
3685 else if (all && strchr(allstr, kbinput) != NULL)
3686 ok = 2;
3687 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003688
Chris Allegrettadb28e962003-01-28 01:23:40 +00003689 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003690}
3691
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003692void total_update(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003693{
David Lawrence Ramsey0bfec6e2005-04-25 20:08:29 +00003694 clearok(edit, TRUE);
3695 wrefresh(edit);
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003696}
3697
3698void total_refresh(void)
3699{
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003700 total_update();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003701 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003702 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003703 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003704}
3705
3706void display_main_list(void)
3707{
3708 bottombars(main_list);
3709}
3710
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003711/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3712 * display the cursor position. Otherwise, we display it only if the
3713 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003714 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003715 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3716 * old_i and old_totsize. That way, we leave the current statusbar
3717 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003718void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003719{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003720 char c;
3721 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003722 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003723 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003724
Chris Allegrettad26ab912003-01-28 01:16:47 +00003725 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003726
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003727 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003728 old_totsize = totsize;
3729
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003730 c = current->data[current_x];
3731 f = current->next;
3732 current->data[current_x] = '\0';
3733 current->next = NULL;
3734 get_totals(fileage, current, NULL, &i);
3735 current->data[current_x] = c;
3736 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003737
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003738 /* Check whether totsize is correct. Else there is a bug
3739 * somewhere. */
3740 assert(current != filebot || i == totsize);
3741
Chris Allegrettad26ab912003-01-28 01:16:47 +00003742 if (constant && ISSET(DISABLE_CURPOS)) {
3743 UNSET(DISABLE_CURPOS);
3744 old_i = i;
3745 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003746 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003747 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003748
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003749 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003750 * unconditionally; otherwise, only display the position when the
3751 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003752 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003753 size_t xpt = xplustabs() + 1;
3754 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003755 int linepct = 100 * current->lineno / totlines;
3756 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003757 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003758
3759 statusbar(
3760 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3761 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003762 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003763 (unsigned long)i, (unsigned long)totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003764 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003765 }
3766
3767 old_i = i;
3768 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003769}
3770
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003771void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003772{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003773 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003774}
3775
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003776#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003777/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003778size_t help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003779{
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003780 int help_cols = (COLS > 24) ? COLS - 8 : 24;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003781
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003782 /* Try to break the line at (COLS - 8) columns if we have more than
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003783 * 24 columns, and at 24 columns otherwise. */
David Lawrence Ramsey40e211b2005-03-19 21:15:30 +00003784 size_t retval = break_line(ptr, help_cols, TRUE);
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003785 size_t retval_save = retval;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003786
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003787 /* Get the length of the entire line up to a null or a newline. */
3788 while (*(ptr + retval) != '\0' && *(ptr + retval) != '\n')
3789 retval += move_mbright(ptr + retval, 0);
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003790
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003791 /* If the entire line doesn't go more than 8 columns beyond where we
3792 * tried to break it, we should display it as-is. Otherwise, we
3793 * should display it only up to the break. */
3794 if (strnlenpt(ptr, retval) > help_cols + 8)
3795 retval = retval_save;
3796
3797 return retval;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003798}
3799
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003800/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003801void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003802{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003803 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003804 /* The line number in help_text of the first displayed help
3805 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003806 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003807 /* no_more means the end of the help text is shown, so don't go
3808 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003809 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003810 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003811
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003812 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003813#ifndef DISABLE_MOUSE
3814 const shortcut *oldshortcut = currshortcut;
3815 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003816 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003817#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003818
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003819 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003820 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003821 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003822 blank_statusbar();
3823
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003824 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003825 help_init();
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003826
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003827 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003828
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003829#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003830 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003831 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003832 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003833#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003834
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003835 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003836 /* Make sure that the help screen's shortcut list will actually
3837 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003838 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003839 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003840 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003841
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003842 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003843
3844 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003845 int i;
3846 int old_line = line;
3847 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003848 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003849
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003850 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003851#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003852 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003853 {
3854 int mouse_x, mouse_y;
3855 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3856 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003857 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003858#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003859 case NANO_PREVPAGE_KEY:
3860 case NANO_PREVPAGE_FKEY:
3861 if (line > 0) {
3862 line -= editwinrows - 2;
3863 if (line < 0)
3864 line = 0;
3865 }
3866 break;
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003867 case NANO_NEXTPAGE_KEY:
3868 case NANO_NEXTPAGE_FKEY:
3869 if (!no_more)
3870 line += editwinrows - 2;
3871 break;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003872 case NANO_PREVLINE_KEY:
3873 if (line > 0)
3874 line--;
3875 break;
3876 case NANO_NEXTLINE_KEY:
3877 if (!no_more)
3878 line++;
3879 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003880 }
3881
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003882 if (kbinput == NANO_REFRESH_KEY)
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003883 total_update();
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003884 else {
3885 if (line == old_line && kbinput != ERR)
3886 goto skip_redisplay;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003887
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003888 blank_edit();
3889 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003890
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003891 /* Calculate where in the text we should be, based on the
3892 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003893 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003894 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003895 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003896 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003897 }
3898
Chris Allegretta4640fe32003-02-10 03:10:03 +00003899 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003900 size_t j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003901
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003902 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003903 ptr += j;
3904 if (*ptr == '\n')
3905 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003906 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003907 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003908
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003909 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003910 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003911 } while (kbinput != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003912
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003913#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003914 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003915#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003916
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003917 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003918 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003919 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003920 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003921 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003922 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003923 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003924
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003925 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003926 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003927
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003928 /* The help_init() at the beginning allocated help_text. Since
3929 * help_text has now been written to the screen, we don't need it
3930 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003931 free(help_text);
3932 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003933}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003934#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003935
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003936/* Highlight the current word being replaced or spell checked. We
3937 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003938void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003939{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003940 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003941 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003942
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003943 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003944 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003945 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003946
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003947 assert(y > 0);
3948
3949 if (word_len > y)
3950 y--;
3951
Chris Allegrettafb62f732000-12-05 11:36:41 +00003952 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003953
Chris Allegrettafb62f732000-12-05 11:36:41 +00003954 if (highlight_flag)
3955 wattron(edit, A_REVERSE);
3956
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003957#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003958 /* This is so we can show zero-length regexes. */
3959 if (word_len == 0)
3960 waddstr(edit, " ");
3961 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003962#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003963 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003964
3965 if (word_len > y)
3966 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003967
3968 if (highlight_flag)
3969 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003970}
3971
David Lawrence Ramseycc814362005-06-05 19:08:59 +00003972#ifndef NDEBUG
3973/* Return what the current line number should be, starting at edittop
3974 * and ending at fileptr. */
3975int check_linenumbers(const filestruct *fileptr)
3976{
3977 int check_line = 0;
3978 const filestruct *filetmp;
3979
3980 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
3981 check_line++;
3982
3983 return check_line;
3984}
3985#endif
3986
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003987#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003988/* Dump the passed-in file structure to stderr. */
3989void dump_buffer(const filestruct *inptr)
3990{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003991 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003992 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003993 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003994 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003995 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003996 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003997
3998 while (inptr != NULL) {
3999 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4000 inptr = inptr->next;
4001 }
4002}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004003
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004004/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004005void dump_buffer_reverse(void)
4006{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004007 const filestruct *fileptr = filebot;
4008
4009 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004010 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004011 fileptr = fileptr->prev;
4012 }
4013}
4014#endif /* DEBUG */
4015
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004016#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004017#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004018#define XLCREDIT_LEN 8
4019
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004020/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004021void do_credits(void)
4022{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004023 int crpos = 0, xlpos = 0;
4024 const char *credits[CREDIT_LEN] = {
4025 NULL, /* "The nano text editor" */
4026 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004027 VERSION,
4028 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004029 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004030 "Chris Allegretta",
4031 "Jordi Mallach",
4032 "Adam Rogoyski",
4033 "Rob Siemborski",
4034 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004035 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004036 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004037 "Ken Tyler",
4038 "Sven Guckes",
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004039 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00004040 "Pauli Virtanen",
4041 "Daniele Medri",
4042 "Clement Laforet",
4043 "Tedi Heriyanto",
4044 "Bill Soudan",
4045 "Christian Weisgerber",
4046 "Erik Andersen",
4047 "Big Gaute",
4048 "Joshua Jensen",
4049 "Ryan Krebs",
4050 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004051 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004052 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004053 "Plattsburgh State University",
4054 "Benet Laboratories",
4055 "Amy Allegretta",
4056 "Linda Young",
4057 "Jeremy Robichaud",
4058 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004059 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004060 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004061 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004062 "Thomas Dickey",
4063 "Pavel Curtis",
4064 "Zeyd Ben-Halim",
4065 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004066 NULL, /* "and anyone else we forgot..." */
4067 NULL, /* "Thank you for using nano!" */
4068 "",
4069 "",
4070 "",
4071 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004072 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004073 "",
4074 "",
4075 "",
4076 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004077 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004078 };
4079
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004080 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004081 N_("The nano text editor"),
4082 N_("version"),
4083 N_("Brought to you by:"),
4084 N_("Special thanks to:"),
4085 N_("The Free Software Foundation"),
4086 N_("For ncurses:"),
4087 N_("and anyone else we forgot..."),
4088 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004089 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004090
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004091 curs_set(0);
4092 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004093 scrollok(edit, TRUE);
4094 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004095 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004096 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004097 blank_statusbar();
4098 blank_bottombars();
4099 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004100 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004101 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004102
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004103 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
4104 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004105 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004106
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004107 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004108 char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004109 size_t start_x;
4110
David Lawrence Ramsey631242d2005-03-15 07:06:54 +00004111 /* Make sure every credit is a valid multibyte string, since
4112 * we can't dynamically set the credits to their multibyte
4113 * equivalents when we need to. Sigh... */
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004114 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004115 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004116
4117 what = mallocstrcpy(NULL, _(xlcredits[xlpos]));
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004118 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004119 } else
4120 what = make_mbstring(credits[crpos]);
4121
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004122 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004123 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
4124 start_x, what);
4125
4126 free(what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004127 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004128
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004129 napms(700);
4130 scroll(edit);
4131 wrefresh(edit);
4132 if (wgetch(edit) != ERR)
4133 break;
4134 napms(700);
4135 scroll(edit);
4136 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004137 }
4138
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004139 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004140 nodelay(edit, FALSE);
4141 curs_set(1);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004142 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004143}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004144#endif