blob: bea1680b39d7a8fa3e0796285054e975cf966c2e [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 Ramseyf28f50e2004-01-09 23:04:55 +00005 * Copyright (C) 1999-2004 Chris Allegretta *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00006 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
Jordi Mallach55381aa2004-11-17 23:17:05 +000022#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000025
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000026#include <stdarg.h>
27#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000028#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000029#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000030#include <ctype.h>
Chris Allegretta6232d662002-05-12 19:52:15 +000031#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000032#include "proto.h"
33#include "nano.h"
34
David Lawrence Ramsey93c4a562004-12-23 21:32:27 +000035#if defined(HAVE_WCHAR_H) && defined(NANO_WIDE)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +000036#include <wchar.h>
37#endif
38
David Lawrence Ramsey74835712004-12-04 17:41:52 +000039static buffer *key_buffer = NULL;
40 /* The default keystroke buffer,
41 * containing all the keystrokes we have
42 * at a given point. */
43static size_t key_buffer_len = 0;
44 /* The length of the default keystroke
45 * buffer. */
46static int statusblank = 0; /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000047 * we call statusbar(), before we
48 * actually blank the statusbar. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000049static bool resetstatuspos = FALSE;
50 /* Should we reset the cursor position
51 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000052
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000053/* Control character compatibility:
54 *
55 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
56 * VT100, and VT220.
57 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
58 * VT220, and VT320.
59 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
60 * VT220, and VT320.
61 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
62 * VT220, and VT320.
63 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
64 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000065 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000066 * ANSI, VT100, and VT220, and which is Backspace under VT320.
67 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000068 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000069 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
70 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000071 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000072 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000073 * on which the VT320 sequences are translated by the keypad to KEY_DC
74 * and [nothing]. We work around this conflict via the REBIND_DELETE
75 * flag: if it's not set, we assume VT320 compatibility, and if it is,
76 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
77 * Hemel for helping work this conflict out.
78 *
79 * Escape sequence compatibility:
80 *
81 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000082 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000083 * console), xterm, rxvt, and Eterm. Among these, there are several
84 * conflicts and omissions, outlined as follows:
85 *
86 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
87 * (Ctrl-I is also Tab on ANSI, which we already support.)
88 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
89 * NumLock off on Linux console; the latter is omitted. (The editing
90 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000091 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000092 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
93 * latter is omitted. (Mouse input will only work properly if the
94 * extended keypad value KEY_MOUSE is generated on mouse events
95 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000096 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000097 * omitted. (The editing keypad is more important to have working
98 * than the function keys, because the functions of the former are not
99 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000100 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000101 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000102 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000103 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000104 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
105 * omitted. (The arrow keys, with or without modifiers, are more
106 * important to have working than the function keys, because the
107 * functions of the former are not arbitrary and the functions of the
108 * latter are.)
109 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
110 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000111 *
112 * Note that Center (5) on the numeric keypad with NumLock off can also
113 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000114
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000115#ifndef NANO_SMALL
116/* Reset all the input routines that rely on character sequences. */
117void reset_kbinput(void)
118{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000119 parse_kbinput(NULL, NULL, NULL, TRUE);
120 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000121}
122#endif
123
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000124/* Read in a sequence of keystrokes from win and save them in the
125 * default keystroke buffer. This should only be called when the
126 * default keystroke buffer is empty. */
127void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000128{
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000129 int input, input_key_code;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000130
131 /* If the keystroke buffer isn't empty, get out. */
132 if (key_buffer != NULL)
133 return;
134
135 /* Read in the first character using blocking input. */
136 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000137
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000138#ifndef NANO_SMALL
139 allow_pending_sigwinch(TRUE);
140#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000141
142#ifdef NANO_WIDE
143 if (!ISSET(NO_UTF8)) {
144 wint_t tmp;
145
146 input_key_code = wget_wch(win, &tmp);
147 input = (int)tmp;
148 } else {
149#endif
150 input = wgetch(win);
151 input_key_code = !is_byte_char(input);
152#ifdef NANO_WIDE
153 }
154#endif
155
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000156#ifndef NANO_SMALL
157 allow_pending_sigwinch(FALSE);
158#endif
159
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000160 /* Increment the length of the keystroke buffer, save the value of
161 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000162 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000163 key_buffer_len++;
164 key_buffer = (buffer *)nmalloc(sizeof(buffer));
165 key_buffer[0].key = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000166 key_buffer[0].key_code =
167#ifdef NANO_WIDE
168 !ISSET(NO_UTF8) ? (input_key_code == KEY_CODE_YES) :
169#endif
170 input_key_code;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000171
172 /* Read in the remaining characters using non-blocking input. */
173 nodelay(win, TRUE);
174
175 while (TRUE) {
176#ifndef NANO_SMALL
177 allow_pending_sigwinch(TRUE);
178#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000179
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000180#ifdef NANO_WIDE
181 if (!ISSET(NO_UTF8)) {
182 wint_t tmp;
183
184 input_key_code = wget_wch(win, &tmp);
185 input = (int)tmp;
186 } else {
187#endif
188 input = wgetch(win);
189 input_key_code = !is_byte_char(input);
190#ifdef NANO_WIDE
191 }
192#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000193 /* If there aren't any more characters, stop reading. */
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000194 if (
195#ifdef NANO_WIDE
196 (!ISSET(NO_UTF8) && input_key_code == ERR) ||
197#endif
198 input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000199 break;
200
201 /* Otherwise, increment the length of the keystroke buffer, save
202 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000203 * if the keystroke is an extended keypad value or FALSE if it
204 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000205 key_buffer_len++;
206 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
207 sizeof(buffer));
208 key_buffer[key_buffer_len - 1].key = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000209 key_buffer[key_buffer_len - 1].key_code =
210#ifdef NANO_WIDE
211 !ISSET(NO_UTF8) ? (input_key_code == KEY_CODE_YES) :
212#endif
213 input_key_code;
214
215#ifndef NANO_SMALL
216 allow_pending_sigwinch(FALSE);
217#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000218 }
219
220 /* Switch back to non-blocking input. */
221 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000222}
223
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000224/* Return the length of the default keystroke buffer. */
225size_t get_buffer_len(void)
226{
227 return key_buffer_len;
228}
229
230/* Return the key values stored in the keystroke buffer input,
231 * discarding the key_code values in it. */
232int *buffer_to_keys(buffer *input, size_t input_len)
233{
234 int *sequence = (int *)nmalloc(input_len * sizeof(int));
235 size_t i;
236
237 for (i = 0; i < input_len; i++)
238 sequence[i] = input[i].key;
239
240 return sequence;
241}
242
243/* Add the contents of the keystroke buffer input to the default
244 * keystroke buffer. */
245void unget_input(buffer *input, size_t input_len)
246{
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000247 buffer *clean_input = NULL;
248 size_t clean_input_len = 0;
249
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000250#ifndef NANO_SMALL
251 allow_pending_sigwinch(TRUE);
252 allow_pending_sigwinch(FALSE);
253#endif
254
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000255#ifdef NANO_WIDE
256 if (!ISSET(NO_UTF8)) {
David Lawrence Ramseyf812e4f2004-12-07 17:35:14 +0000257 size_t i;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000258 char *key = charalloc(MB_CUR_MAX);
David Lawrence Ramsey60448892004-12-08 16:52:52 +0000259
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000260 /* Keep all valid wide keystrokes, discarding the others. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000261 for (i = 0; i < input_len; i++) {
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000262 int key_len = input[i].key_code ? 1 :
David Lawrence Ramseyc2ac02f2004-12-09 03:05:45 +0000263 wctomb(key, (wchar_t)input[i].key);
David Lawrence Ramseyeae97ca2004-12-07 22:24:03 +0000264
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000265 if (key_len != -1) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000266 clean_input_len++;
267 clean_input = (buffer *)nrealloc(clean_input,
268 clean_input_len * sizeof(buffer));
269
270 clean_input[clean_input_len - 1].key = input[i].key;
271 clean_input[clean_input_len - 1].key_code =
272 input[i].key_code;
273 }
274 }
David Lawrence Ramsey60448892004-12-08 16:52:52 +0000275
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000276 free(key);
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000277 } else {
278#endif
279 clean_input = input;
280 clean_input_len = input_len;
281#ifdef NANO_WIDE
282 }
283#endif
284
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000285 /* If input is empty, get out. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000286 if (clean_input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000287 return;
288
289 /* If adding input would put the default keystroke buffer beyond
290 * maximum capacity, only add enough of input to put it at maximum
291 * capacity. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000292 if (key_buffer_len + clean_input_len < key_buffer_len)
293 clean_input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000294
295 /* Add the length of input to the length of the default keystroke
296 * buffer, and reallocate the default keystroke buffer so that it
297 * has enough room for input. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000298 key_buffer_len += clean_input_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000299 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
300 sizeof(buffer));
301
302 /* If the default keystroke buffer wasn't empty before, move its
303 * beginning forward far enough so that we can add input to its
304 * beginning. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000305 if (key_buffer_len > clean_input_len)
306 memmove(key_buffer + clean_input_len, key_buffer,
307 (key_buffer_len - clean_input_len) * sizeof(buffer));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000308
309 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000310 memcpy(key_buffer, clean_input, clean_input_len * sizeof(buffer));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000311}
312
313/* Put back the character stored in kbinput. If func_key is TRUE and
314 * the character is out of byte range, interpret it as an extended
315 * keypad value. If meta_key is TRUE, put back the Escape character
316 * after putting back kbinput. */
317void unget_kbinput(int kbinput, bool meta_key, bool func_key)
318{
319 buffer input;
320
321 input.key = kbinput;
322 input.key_code = (func_key && !is_byte_char(kbinput));
323
324 unget_input(&input, 1);
325
326 if (meta_key) {
327 input.key = NANO_CONTROL_3;
328 input.key_code = FALSE;
329 unget_input(&input, 1);
330 }
331}
332
333/* Try to read input_len characters from the default keystroke buffer.
334 * If the default keystroke buffer is empty and win isn't NULL, try to
335 * read in more characters from win and add them to the default
336 * keystroke buffer before doing anything else. If the default
337 * keystroke buffer is empty and win is NULL, return NULL. */
338buffer *get_input(WINDOW *win, size_t input_len)
339{
340 buffer *input;
341
342#ifndef NANO_SMALL
343 allow_pending_sigwinch(TRUE);
344 allow_pending_sigwinch(FALSE);
345#endif
346
347 if (key_buffer_len == 0) {
348 if (win != NULL)
349 get_buffer(win);
350
351 if (key_buffer_len == 0)
352 return NULL;
353 }
354
355 /* If input_len is greater than the length of the default keystroke
356 * buffer, only read the number of characters in the default
357 * keystroke buffer. */
358 if (input_len > key_buffer_len)
359 input_len = key_buffer_len;
360
361 /* Subtract input_len from the length of the default keystroke
362 * buffer, and allocate the keystroke buffer input so that it
363 * has enough room for input_len keystrokes. */
364 key_buffer_len -= input_len;
365 input = (buffer *)nmalloc(input_len * sizeof(buffer));
366
367 /* Copy input_len characters from the beginning of the default
368 * keystroke buffer into input. */
369 memcpy(input, key_buffer, input_len * sizeof(buffer));
370
371 /* If the default keystroke buffer is empty, mark it as such. */
372 if (key_buffer_len == 0) {
373 free(key_buffer);
374 key_buffer = NULL;
375 /* If the default keystroke buffer isn't empty, move its
376 * beginning forward far enough back so that the keystrokes in input
377 * are no longer at its beginning. */
378 } else {
379 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
380 sizeof(buffer));
381 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
382 sizeof(buffer));
383 }
384
385 return input;
386}
387
388/* Read in a single character. If it's ignored, swallow it and go on.
389 * Otherwise, try to translate it from ASCII, meta key sequences, escape
390 * sequences, and/or extended keypad values. Set meta_key to TRUE when
391 * we get a meta key sequence, and set func_key to TRUE when we get an
392 * extended keypad value. Supported extended keypad values consist of
393 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
394 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
395 * the function keypad (F1-F16), and the numeric keypad with NumLock
396 * off. Assume nodelay(win) is FALSE. */
397int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
398{
399 int kbinput;
400
401 /* Read in a character and interpret it. Continue doing this until
402 * we get a recognized value or sequence. */
403 while ((kbinput = parse_kbinput(win, meta_key, func_key
404#ifndef NANO_SMALL
405 , FALSE
406#endif
407 )) == ERR);
408
409 return kbinput;
410}
411
412/* Translate ASCII characters, extended keypad values, and escape
413 * sequences into their corresponding key values. Set meta_key to TRUE
414 * when we get a meta key sequence, and set func_key to TRUE when we get
415 * a function key. Assume nodelay(win) is FALSE. */
416int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000417#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000418 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000419#endif
420 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000421
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000422{
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +0000423 static int escapes = 0, word_digits = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000424 buffer *kbinput;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000425 int retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000426
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000427 if (reset) {
428 escapes = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000429 word_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000430 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000431 }
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000432
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000433 *meta_key = FALSE;
434 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000435
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000436 /* Read in a character. */
437 while ((kbinput = get_input(win, 1)) == NULL);
438
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000439 if (kbinput->key_code || is_byte_char(kbinput->key)) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000440 /* If we got an extended keypad value or an ASCII character,
441 * translate it. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000442 switch (kbinput->key) {
443 case ERR:
444 break;
445 case NANO_CONTROL_3:
446 /* Increment the escape counter. */
447 escapes++;
448 switch (escapes) {
449 case 1:
450 /* One escape: wait for more input. */
451 case 2:
452 /* Two escapes: wait for more input. */
453 break;
454 default:
455 /* More than two escapes: reset the escape
456 * counter and wait for more input. */
457 escapes = 0;
458 }
459 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000460#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000461 /* Since we don't change the default SIGWINCH handler when
462 * NANO_SMALL is defined, KEY_RESIZE is never generated.
463 * Also, Slang and SunOS 5.7-5.9 don't support
464 * KEY_RESIZE. */
465 case KEY_RESIZE:
466 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000467#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000468#ifdef PDCURSES
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000469 case KEY_SHIFT_L:
470 case KEY_SHIFT_R:
471 case KEY_CONTROL_L:
472 case KEY_CONTROL_R:
473 case KEY_ALT_L:
474 case KEY_ALT_R:
475 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000476#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000477 default:
478 switch (escapes) {
479 case 0:
480 switch (kbinput->key) {
481 case NANO_CONTROL_8:
482 retval = ISSET(REBIND_DELETE) ?
483 NANO_DELETE_KEY :
484 NANO_BACKSPACE_KEY;
485 break;
486 case KEY_DOWN:
487 retval = NANO_NEXTLINE_KEY;
488 break;
489 case KEY_UP:
490 retval = NANO_PREVLINE_KEY;
491 break;
492 case KEY_LEFT:
493 retval = NANO_BACK_KEY;
494 break;
495 case KEY_RIGHT:
496 retval = NANO_FORWARD_KEY;
497 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000498#ifdef KEY_HOME
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000499 /* HP-UX 10 and 11 don't support
500 * KEY_HOME. */
501 case KEY_HOME:
502 retval = NANO_HOME_KEY;
503 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000504#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000505 case KEY_BACKSPACE:
506 retval = NANO_BACKSPACE_KEY;
507 break;
508 case KEY_DC:
509 retval = ISSET(REBIND_DELETE) ?
510 NANO_BACKSPACE_KEY :
511 NANO_DELETE_KEY;
512 break;
513 case KEY_IC:
514 retval = NANO_INSERTFILE_KEY;
515 break;
516 case KEY_NPAGE:
517 retval = NANO_NEXTPAGE_KEY;
518 break;
519 case KEY_PPAGE:
520 retval = NANO_PREVPAGE_KEY;
521 break;
522 case KEY_ENTER:
523 retval = NANO_ENTER_KEY;
524 break;
525 case KEY_A1: /* Home (7) on numeric
526 * keypad with NumLock
527 * off. */
528 retval = NANO_HOME_KEY;
529 break;
530 case KEY_A3: /* PageUp (9) on numeric
531 * keypad with NumLock
532 * off. */
533 retval = NANO_PREVPAGE_KEY;
534 break;
535 case KEY_B2: /* Center (5) on numeric
536 * keypad with NumLock
537 * off. */
538 break;
539 case KEY_C1: /* End (1) on numeric
540 * keypad with NumLock
541 * off. */
542 retval = NANO_END_KEY;
543 break;
544 case KEY_C3: /* PageDown (4) on
545 * numeric keypad with
546 * NumLock off. */
547 retval = NANO_NEXTPAGE_KEY;
548 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000549#ifdef KEY_BEG
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000550 /* Slang doesn't support KEY_BEG. */
551 case KEY_BEG: /* Center (5) on numeric
552 * keypad with NumLock
553 * off. */
554 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000555#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000556#ifdef KEY_END
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000557 /* HP-UX 10 and 11 don't support KEY_END. */
558 case KEY_END:
559 retval = NANO_END_KEY;
560 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000561#endif
562#ifdef KEY_SUSPEND
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000563 /* Slang doesn't support KEY_SUSPEND. */
564 case KEY_SUSPEND:
565 retval = NANO_SUSPEND_KEY;
566 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000567#endif
568#ifdef KEY_SLEFT
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000569 /* Slang doesn't support KEY_SLEFT. */
570 case KEY_SLEFT:
571 retval = NANO_BACK_KEY;
572 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000573#endif
574#ifdef KEY_SRIGHT
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000575 /* Slang doesn't support KEY_SRIGHT. */
576 case KEY_SRIGHT:
577 retval = NANO_FORWARD_KEY;
578 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000579#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000580 default:
581 retval = kbinput->key;
582 break;
583 }
584 break;
585 case 1:
586 /* One escape followed by a non-escape: escape
587 * sequence mode. Reset the escape counter. If
588 * there aren't any other keys waiting, we have
589 * a meta key sequence, so set meta_key to TRUE
590 * and save the lowercase version of the
591 * non-escape character as the result. If there
592 * are other keys waiting, we have a true escape
593 * sequence, so interpret it. */
594 escapes = 0;
595 if (get_buffer_len() == 0) {
596 *meta_key = TRUE;
597 retval = tolower(kbinput->key);
598 } else {
599 buffer *escape_kbinput;
600 int *sequence;
601 size_t seq_len;
602 bool ignore_seq;
603
604 /* Put back the non-escape character, get
605 * the complete escape sequence, translate
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +0000606 * the sequence into its corresponding key
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000607 * value, and save that as the result. */
608 unget_input(kbinput, 1);
609 seq_len = get_buffer_len();
610 escape_kbinput = get_input(NULL, seq_len);
611 sequence = buffer_to_keys(escape_kbinput,
612 seq_len);
613 retval = get_escape_seq_kbinput(sequence,
614 seq_len, &ignore_seq);
615
616 /* If the escape sequence is unrecognized
617 * and not ignored, put back all of its
618 * characters except for the initial
619 * escape. */
620 if (retval == ERR && !ignore_seq)
621 unget_input(escape_kbinput, seq_len);
622
623 free(escape_kbinput);
624 }
625 break;
626 case 2:
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000627 /* Two escapes followed by one or more decimal
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000628 * digits: word sequence mode. If the word
629 * sequence's range is limited to 6XXXX (the
630 * first digit is in the '0' to '6' range and
631 * it's the first digit, or it's in the '0' to
632 * '9' range and it's not the first digit),
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000633 * increment the word sequence counter and
634 * interpret the digit. If the word sequence's
635 * range is not limited to 6XXXX, fall
636 * through. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000637 if (('0' <= kbinput->key && kbinput->key <= '6'
638 && word_digits == 0) ||
639 ('0' <= kbinput->key && kbinput->key <= '9'
640 && word_digits > 0)) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000641 int word_kbinput;
642
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000643 word_digits++;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000644 word_kbinput = get_word_kbinput(kbinput->key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000645#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000646 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000647#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000648 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000649
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000650 if (word_kbinput != ERR) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000651 /* If we've read in a complete word
652 * sequence, reset the word sequence
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000653 * counter and the escape counter,
654 * and put back the corresponding word
655 * value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000656 word_digits = 0;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000657 escapes = 0;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000658 unget_kbinput(word_kbinput, FALSE,
659 FALSE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000660 }
661 } else {
662 /* Reset the escape counter. */
663 escapes = 0;
664 if (word_digits == 0)
665 /* Two escapes followed by a non-decimal
666 * digit or a decimal digit that would
667 * create a word sequence greater than
668 * 6XXXX, and we're not in the middle of
669 * a word sequence: control character
670 * sequence mode. Interpret the control
671 * sequence and save the corresponding
672 * control character as the result. */
673 retval = get_control_kbinput(kbinput->key);
674 else {
675 /* If we're in the middle of a word
676 * sequence, reset the word sequence
677 * counter and save the character we got
678 * as the result. */
679 word_digits = 0;
680 retval = kbinput->key;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000681 }
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000682 }
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000683 break;
684 }
685 }
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000686
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000687 /* If we have a result and it's an extended keypad value, set
688 * func_key to TRUE. */
689 if (retval != ERR)
690 *func_key = !is_byte_char(retval);
691 } else
692 /* If we didn't get an extended keypad value or an ASCII
693 * character, leave it as-is. */
694 retval = kbinput->key;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000695
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000696#ifdef DEBUG
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000697 fprintf(stderr, "parse_kbinput(): kbinput->key = %d, meta_key = %d, func_key = %d, escapes = %d, word_digits = %d, retval = %d\n", kbinput->key, (int)*meta_key, (int)*func_key, escapes, word_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000698#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000699
700 /* Return the result. */
701 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000702}
703
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000704/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000705 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000706 * are generated when the keypad doesn't support the needed keys. If
707 * the escape sequence is recognized but we want to ignore it, return
708 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
709 * set ignore_seq to FALSE. Assume that Escape has already been read
710 * in. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000711int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000712 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000713{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000714 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000715
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000716 *ignore_seq = FALSE;
717
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000718 if (seq_len > 1) {
719 switch (sequence[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000720 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000721 switch (sequence[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000722 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000723 if (seq_len >= 3) {
724 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000725 case 'P': /* Esc O 2 P == F13 on
726 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000727 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000728 break;
729 case 'Q': /* Esc O 2 Q == F14 on
730 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000731 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000732 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000733 case 'R': /* Esc O 2 R == F15 on
734 * xterm. */
735 retval = KEY_F(15);
736 break;
737 case 'S': /* Esc O 2 S == F16 on
738 * xterm. */
739 retval = KEY_F(16);
740 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000741 }
742 }
743 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000744 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
745 case 'B': /* Esc O B == Down on
746 * VT100/VT320/xterm. */
747 case 'C': /* Esc O C == Right on
748 * VT100/VT320/xterm. */
749 case 'D': /* Esc O D == Left on
750 * VT100/VT320/xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000751 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000752 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000753 case 'E': /* Esc O E == Center (5) on numeric keypad
754 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000755 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000756 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000757 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000758 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000759 break;
760 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000761 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000762 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000763 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000764 * NumLock off on VT100/VT220/VT320/xterm/
765 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000766 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000767 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000768 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000769 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000770 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000771 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000772 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000773 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000774 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000775 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000776 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000777 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000778 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000779 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000780 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000781 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000782 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000783 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000784 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000785 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000786 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000787 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000788 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000789 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000790 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000791 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000792 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000793 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000794 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000795 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000796 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000797 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000798 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000799 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000800 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000801 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000802 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000803 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000804 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000805 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000806 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000807 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000808 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000809 * NumLock off on VT100/VT220/VT320/xterm/
810 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000811 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000812 break;
813 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000814 * NumLock off on VT100/VT220/VT320/xterm/
815 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000816 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000817 break;
818 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000819 * NumLock off on VT100/VT220/VT320/xterm/
820 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000821 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000822 break;
823 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000824 * NumLock off on VT100/VT220/VT320/xterm/
825 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000826 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000827 break;
828 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000829 * with NumLock off on VT100/VT220/VT320/
830 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000831 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000832 break;
833 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000834 * NumLock off on VT100/VT220/VT320/xterm/
835 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000836 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000837 break;
838 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000839 * with NumLock off on VT100/VT220/VT320/
840 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000841 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000842 break;
843 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000844 * with NumLock off on VT100/VT220/VT320/
845 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000846 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000847 break;
848 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000849 * with NumLock off on VT100/VT220/VT320/
850 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000851 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000852 break;
853 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000854 * keypad with NumLock off on VT100/VT220/
855 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000856 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000857 break;
858 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000859 * with NumLock off on VT100/VT220/VT320/
860 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000861 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000862 break;
863 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000864 * with NumLock off on VT100/VT220/VT320/
865 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000866 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000867 break;
868 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000869 * with NumLock off on VT100/VT220/VT320/
870 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000871 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000872 break;
873 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000874 * with NumLock off on VT100/VT220/VT320/
875 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000876 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000877 break;
878 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000879 * with NumLock off on VT100/VT220/VT320/
880 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000881 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000882 break;
883 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000884 * with NumLock off on VT100/VT220/VT320/
885 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000886 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000887 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000888 }
889 break;
890 case 'o':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000891 switch (sequence[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000892 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000893 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000894 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000895 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000896 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000897 break;
898 }
899 break;
900 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000901 switch (sequence[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000902 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000903 if (seq_len >= 3) {
904 switch (sequence[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000905 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
906 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000907 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000908 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000909 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
910 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000911 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000912 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000913 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
914 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000915 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000916 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000917 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
918 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000919 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000920 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000921 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
922 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000923 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000924 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000925 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000926 * VT220/VT320/Linux console/
927 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000928 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000929 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000930 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000931 * VT220/VT320/Linux console/
932 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000933 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000934 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000935 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000936 * VT220/VT320/Linux console/
937 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000938 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000939 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000940 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000941 if (seq_len >= 4) {
942 switch (sequence[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000943 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000944 if (seq_len >= 5) {
945 switch (sequence[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000946 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
947 * xterm. */
948 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
949 * xterm. */
950 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
951 * xterm. */
952 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
953 * xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000954 retval = get_escape_seq_abcd(sequence[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000955 break;
956 }
957 }
958 break;
959 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000960 if (seq_len >= 5) {
961 switch (sequence[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000962 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
963 * xterm. */
964 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
965 * xterm. */
966 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
967 * xterm. */
968 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
969 * xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000970 retval = get_escape_seq_abcd(sequence[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000971 break;
972 }
973 }
974 break;
975 }
976 }
977 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000978 default: /* Esc [ 1 ~ == Home on
979 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000980 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000981 break;
982 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000983 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000984 break;
985 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000986 if (seq_len >= 3) {
987 switch (sequence[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000988 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000989 * VT220/VT320/Linux console/
990 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000991 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000992 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000993 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000994 * VT220/VT320/Linux console/
995 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000996 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000997 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000998 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000999 * VT220/VT320/Linux console/
1000 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001001 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001002 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001003 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001004 * VT220/VT320/Linux console/
1005 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001006 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001007 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001008 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001009 * VT220/VT320/Linux console/
1010 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001011 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001012 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001013 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001014 * VT220/VT320/Linux console/
1015 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001016 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001017 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +00001018 case '8': /* Esc [ 2 8 ~ == F15 on
1019 * VT220/VT320/Linux console/
1020 * rxvt/Eterm. */
1021 retval = KEY_F(15);
1022 break;
1023 case '9': /* Esc [ 2 9 ~ == F16 on
1024 * VT220/VT320/Linux console/
1025 * rxvt/Eterm. */
1026 retval = KEY_F(16);
1027 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001028 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001029 * VT220/VT320/Linux console/
1030 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001031 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001032 break;
1033 }
1034 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001035 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001036 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
1037 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001038 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001039 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001040 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001041 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001042 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001043 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001044 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
1045 * Linux console/xterm; Esc [ 5 ^ ==
1046 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001047 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001048 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001049 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
1050 * Linux console/xterm; Esc [ 6 ^ ==
1051 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001052 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001053 break;
1054 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001055 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001056 break;
1057 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001058 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001059 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001060 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001062 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001063 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001064 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001065 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001066 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001067 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001068 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001069 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001070 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001071 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001072 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001073 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001074 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001075 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001076 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001077 * rxvt/Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001078 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001079 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001080 case 'E': /* Esc [ E == Center (5) on numeric keypad
1081 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +00001082 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001083 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001084 case 'F': /* Esc [ F == End on FreeBSD
1085 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001086 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001087 break;
1088 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001089 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001090 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001091 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001092 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001093 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001094 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001095 break;
1096 case 'I': /* Esc [ I == PageUp on FreeBSD
1097 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001098 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001099 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001100 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001101 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001102 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001103 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001104 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001105 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001106 break;
1107 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001108 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001109 break;
1110 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001111 if (seq_len >= 3) {
1112 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001113 case 'P': /* Esc [ O P == F1 on
1114 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001115 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001116 break;
1117 case 'Q': /* Esc [ O Q == F2 on
1118 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001119 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001120 break;
1121 case 'R': /* Esc [ O R == F3 on
1122 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001123 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001124 break;
1125 case 'S': /* Esc [ O S == F4 on
1126 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001127 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001128 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001129 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001130 } else {
1131 /* Esc [ O == F3 on FreeBSD console. */
1132 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001133 }
1134 break;
1135 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001136 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001137 break;
1138 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001139 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001140 break;
1141 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001142 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001143 break;
1144 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001145 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001146 break;
1147 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001148 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001149 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001150 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001151 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001152 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001153 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001154 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001155 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001156 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001157 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001158 break;
1159 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001160 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001161 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001162 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001163 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001164 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001165 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001166 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001167 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001168 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001169 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001170 case 'c': /* Esc [ c == Shift-Right on rxvt/
1171 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001172 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001173 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001174 break;
1175 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001176 if (seq_len >= 3) {
1177 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001178 case 'A': /* Esc [ [ A == F1 on Linux
1179 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001180 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001181 break;
1182 case 'B': /* Esc [ [ B == F2 on Linux
1183 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001184 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001185 break;
1186 case 'C': /* Esc [ [ C == F3 on Linux
1187 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001188 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001189 break;
1190 case 'D': /* Esc [ [ D == F4 on Linux
1191 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001192 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001193 break;
1194 case 'E': /* Esc [ [ E == F5 on Linux
1195 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001196 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001197 break;
1198 }
1199 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001200 break;
1201 }
1202 break;
1203 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001204 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001205
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001206#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001207 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001208#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001209
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001210 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001211}
1212
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001213/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001214 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001215 * to many escape sequences. */
1216int get_escape_seq_abcd(int kbinput)
1217{
1218 switch (tolower(kbinput)) {
1219 case 'a':
1220 return NANO_PREVLINE_KEY;
1221 case 'b':
1222 return NANO_NEXTLINE_KEY;
1223 case 'c':
1224 return NANO_FORWARD_KEY;
1225 case 'd':
1226 return NANO_BACK_KEY;
1227 default:
1228 return ERR;
1229 }
1230}
1231
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001232/* Translate a word sequence: turn a five-digit decimal number from
1233 * 00000 to 65535 into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001234int get_word_kbinput(int kbinput
1235#ifndef NANO_SMALL
1236 , bool reset
1237#endif
1238 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001239{
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001240 static int word_digits = 0, word_kbinput = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001241 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001242
1243#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001244 if (reset) {
1245 word_digits = 0;
1246 word_kbinput = 0;
1247 return ERR;
1248 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001249#endif
1250
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001251 /* Increment the word digit counter. */
1252 word_digits++;
1253
1254 switch (word_digits) {
1255 case 1:
1256 /* One digit: reset the word sequence holder and add the
1257 * digit we got to the 10000's position of the word sequence
1258 * holder. */
1259 word_kbinput = 0;
1260 if ('0' <= kbinput && kbinput <= '6')
1261 word_kbinput += (kbinput - '0') * 10000;
1262 else
1263 /* If the character we got isn't a decimal digit, or if
1264 * it is and it would put the word sequence out of word
1265 * range, save it as the result. */
1266 retval = kbinput;
1267 break;
1268 case 2:
1269 /* Two digits: add the digit we got to the 1000's position
1270 * of the word sequence holder. */
1271 if (('0' <= kbinput && kbinput <= '5') ||
1272 (word_kbinput < 60000 && '6' <= kbinput &&
1273 kbinput <= '9'))
1274 word_kbinput += (kbinput - '0') * 1000;
1275 else
1276 /* If the character we got isn't a decimal digit, or if
1277 * it is and it would put the word sequence out of word
1278 * range, save it as the result. */
1279 retval = kbinput;
1280 break;
1281 case 3:
1282 /* Three digits: add the digit we got to the 100's position
1283 * of the word sequence holder. */
1284 if (('0' <= kbinput && kbinput <= '5') ||
1285 (word_kbinput < 65000 && '6' <= kbinput &&
1286 kbinput <= '9'))
1287 word_kbinput += (kbinput - '0') * 100;
1288 else
1289 /* If the character we got isn't a decimal digit, or if
1290 * it is and it would put the word sequence out of word
1291 * range, save it as the result. */
1292 retval = kbinput;
1293 break;
1294 case 4:
1295 /* Four digits: add the digit we got to the 10's position of
1296 * the word sequence holder. */
1297 if (('0' <= kbinput && kbinput <= '3') ||
1298 (word_kbinput < 65500 && '4' <= kbinput &&
1299 kbinput <= '9'))
1300 word_kbinput += (kbinput - '0') * 10;
1301 else
1302 /* If the character we got isn't a decimal digit, or if
1303 * it is and it would put the word sequence out of word
1304 * range, save it as the result. */
1305 retval = kbinput;
1306 break;
1307 case 5:
1308 /* Five digits: add the digit we got to the 1's position of
1309 * the word sequence holder, and save the corresponding word
1310 * value as the result. */
1311 if (('0' <= kbinput && kbinput <= '5') ||
1312 (word_kbinput < 65530 && '6' <= kbinput &&
1313 kbinput <= '9')) {
1314 word_kbinput += (kbinput - '0');
1315 retval = word_kbinput;
1316 } else
1317 /* If the character we got isn't a decimal digit, or if
1318 * it is and it would put the word sequence out of word
1319 * range, save it as the result. */
1320 retval = kbinput;
1321 break;
1322 default:
1323 /* More than three digits: save the character we got as the
1324 * result. */
1325 retval = kbinput;
1326 break;
1327 }
1328
1329 /* If we have a result, reset the word digit counter and the word
1330 * sequence holder. */
1331 if (retval != ERR) {
1332 word_digits = 0;
1333 word_kbinput = 0;
1334 }
1335
1336#ifdef DEBUG
1337 fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word_kbinput = %d, retval = %d\n", kbinput, word_digits, word_kbinput, retval);
1338#endif
1339
1340 return retval;
1341}
1342
1343/* Translate a control character sequence: turn an ASCII non-control
1344 * character into its corresponding control character. */
1345int get_control_kbinput(int kbinput)
1346{
1347 int retval;
1348
1349 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1350 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1351 kbinput == '`')
1352 retval = NANO_CONTROL_SPACE;
1353 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1354 else if ('3' <= kbinput && kbinput <= '7')
1355 retval = kbinput - 24;
1356 /* Ctrl-8 (Ctrl-?) */
1357 else if (kbinput == '8' || kbinput == '?')
1358 retval = NANO_CONTROL_8;
1359 /* Ctrl-A to Ctrl-_ */
1360 else if ('A' <= kbinput && kbinput <= '_')
1361 retval = kbinput - 64;
1362 /* Ctrl-a to Ctrl-~ */
1363 else if ('a' <= kbinput && kbinput <= '~')
1364 retval = kbinput - 96;
1365 else
1366 retval = kbinput;
1367
1368#ifdef DEBUG
1369 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1370#endif
1371
1372 return retval;
1373}
1374
1375/* Read in a string of characters verbatim, and return the length of the
1376 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1377int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1378{
1379 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001380
1381 /* Turn off flow control characters if necessary so that we can type
1382 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001383 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001384 if (ISSET(PRESERVE))
1385 disable_flow_control();
1386 keypad(win, FALSE);
1387
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001388 /* Read in a stream of characters and interpret it if possible. */
1389 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001390
1391 /* Turn flow control characters back on if necessary and turn the
1392 * keypad back on now that we're done. */
1393 if (ISSET(PRESERVE))
1394 enable_flow_control();
1395 keypad(win, TRUE);
1396
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001397 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001398}
1399
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001400/* Read in a stream of all available characters. Translate the first
1401 * few characters of the input into the corresponding word value if
1402 * possible. After that, leave the input as-is. */
1403int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001404{
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001405 buffer *kbinput, *sequence;
1406 int word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001407
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001408 /* Read in the first keystroke. */
1409 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001410
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001411 /* Check whether the first keystroke is a decimal digit. */
1412 word = get_word_kbinput(kbinput->key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001413#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001414 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001415#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001416 );
1417
1418 /* If the first keystroke isn't a decimal digit, put back the first
1419 * keystroke. */
1420 if (word != ERR)
1421 unget_input(kbinput, 1);
1422 /* Otherwise, read in keystrokes until we have a complete word
1423 * sequence, and put back the corresponding word value. */
1424 else {
1425 buffer word_kbinput;
1426
1427 while (word == ERR) {
1428 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001429
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001430 word = get_word_kbinput(kbinput->key
1431#ifndef NANO_SMALL
1432 , FALSE
1433#endif
1434 );
1435 }
1436
1437 word_kbinput.key = word;
1438 word_kbinput.key_code = FALSE;
1439
1440 unget_input(&word_kbinput, 1);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001441 }
1442
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001443 /* Get the complete sequence, and save the key values in it as the
1444 * result. */
1445 *kbinput_len = get_buffer_len();
1446 sequence = get_input(NULL, *kbinput_len);
1447 retval = buffer_to_keys(sequence, *kbinput_len);
1448 free(sequence);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001449
1450 return retval;
1451}
1452
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001453#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001454/* Check for a mouse event, and if one's taken place, save the
1455 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001456 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1457 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001458 * place on it, figure out which shortcut was clicked and put back the
1459 * equivalent keystroke(s). Return FALSE if no keystrokes were
1460 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001461 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001462bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001463{
1464 MEVENT mevent;
1465
1466 *mouse_x = -1;
1467 *mouse_y = -1;
1468
1469 /* First, get the actual mouse event. */
1470 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001471 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001472
1473 /* Save the screen coordinates where the mouse event took place. */
1474 *mouse_x = mevent.x;
1475 *mouse_y = mevent.y;
1476
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001477 /* If we're allowing shortcuts, the current shortcut list is being
1478 * displayed on the last two lines of the screen, and the mouse
1479 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001480 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001481 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1482 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001483 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001484 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001485 /* The number of shortcuts in the current shortcut list. */
1486 const shortcut *s = currshortcut;
1487 /* The actual shortcut we clicked on, starting at the first
1488 * one in the current shortcut list. */
1489
1490 /* Get the shortcut lists' length. */
1491 if (currshortcut == main_list)
1492 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001493 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001494 currslen = length_of_list(currshortcut);
1495
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001496 /* We don't show any more shortcuts than the main list
1497 * does. */
1498 if (currslen > MAIN_VISIBLE)
1499 currslen = MAIN_VISIBLE;
1500 }
1501
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001502 /* Calculate the width of each shortcut in the list (it's the
1503 * same for all of them). */
1504 if (currslen < 2)
1505 i = COLS / 6;
1506 else
1507 i = COLS / ((currslen / 2) + (currslen % 2));
1508
1509 /* Calculate the y-coordinates relative to the beginning of
1510 * bottomwin, i.e, the bottom three lines of the screen. */
1511 j = *mouse_y - (editwinrows + 3);
1512
1513 /* If we're on the statusbar, beyond the end of the shortcut
1514 * list, or beyond the end of a shortcut on the right side of
1515 * the screen, don't do anything. */
1516 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001517 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001518 j = (*mouse_x / i) * 2 + j;
1519 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001520 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001521
1522 /* Go through the shortcut list to determine which shortcut was
1523 * clicked. */
1524 for (; j > 0; j--)
1525 s = s->next;
1526
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001527 /* And put back the equivalent key. Assume that each shortcut
1528 * has, at the very least, an equivalent control key, an
1529 * equivalent primary meta key sequence, or both. */
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001530 if (s->ctrlval != NANO_NO_KEY)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001531 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001532 else if (s->metaval != NANO_NO_KEY)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001533 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001534
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001535 return TRUE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001536 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001537 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001538}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001539#endif /* !DISABLE_MOUSE */
1540
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001541const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001542 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001543{
1544 const shortcut *s = s_list;
1545 size_t slen = length_of_list(s_list);
1546
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001547#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001548 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 +00001549#endif
1550
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001551 /* Check for shortcuts. */
1552 for (; slen > 0; slen--) {
1553 /* We've found a shortcut if:
1554 *
1555 * 1. The key exists.
1556 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001557 * 3. meta_key is TRUE and the key is the primary or
1558 * miscellaneous meta sequence in the shortcut list.
1559 * 4. func_key is TRUE and the key is a function key in the
1560 * shortcut list. */
1561
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001562 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1563 (*meta_key == TRUE && (*kbinput == s->metaval ||
1564 *kbinput == s->miscval)) || (*func_key == TRUE &&
1565 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001566 break;
1567 }
1568
1569 s = s->next;
1570 }
1571
1572 /* Translate the shortcut to either its control key or its meta key
1573 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001574 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001575 if (slen > 0) {
1576 if (s->ctrlval != NANO_NO_KEY) {
1577 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001578 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001579 *kbinput = s->ctrlval;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001580 } else if (s->metaval != NANO_NO_KEY) {
1581 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001582 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001583 *kbinput = s->metaval;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001584 }
1585 return s;
1586 }
1587
1588 return NULL;
1589}
1590
1591#ifndef NANO_SMALL
1592const toggle *get_toggle(int kbinput, bool meta_key)
1593{
1594 const toggle *t = toggles;
1595
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001596#ifdef DEBUG
1597 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1598#endif
1599
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001600 /* Check for toggles. */
1601 for (; t != NULL; t = t->next) {
1602 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001603 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001604 if (meta_key && kbinput == t->val)
1605 break;
1606 }
1607
1608 return t;
1609}
1610#endif /* !NANO_SMALL */
1611
Chris Allegretta6df90f52002-07-19 01:08:59 +00001612/* Return the placewewant associated with current_x. That is, xplustabs
1613 * is the zero-based column position of the cursor. Value is no smaller
1614 * than current_x. */
1615size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001616{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001617 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001618}
1619
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001620/* actual_x() gives the index in str of the character displayed at
1621 * column xplus. That is, actual_x() is the largest value such that
1622 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
1623size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001624{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001625 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00001626 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001627 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00001628 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001629
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001630 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001631
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001632 while (*str != '\0') {
1633 int str_len = parse_char(str, NULL, &length
1634#ifdef NANO_WIDE
1635 , NULL
1636#endif
1637 );
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001638
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001639 if (length > xplus)
1640 break;
1641
1642 i += str_len;
1643 str += str_len;
1644 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001645
Chris Allegretta6df90f52002-07-19 01:08:59 +00001646 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00001647}
1648
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00001649/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001650 * columns wide are the first size characters of str? */
1651size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00001652{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001653 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001654 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001655
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001656 if (size == 0)
1657 return 0;
1658
1659 assert(str != NULL);
1660
1661 while (*str != '\0') {
1662 int str_len = parse_char(str, NULL, &length
1663#ifdef NANO_WIDE
1664 , NULL
1665#endif
1666 );
1667
1668 str += str_len;
1669
1670 if (size <= str_len)
1671 break;
1672
1673 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001674 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001675
Chris Allegretta6df90f52002-07-19 01:08:59 +00001676 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001677}
1678
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001679/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001680size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001681{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00001682 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001683}
1684
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001685void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001686{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001687 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001688}
1689
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001690void blank_edit(void)
1691{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001692 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001693 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001694 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001695}
1696
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001697void blank_statusbar(void)
1698{
1699 mvwaddstr(bottomwin, 0, 0, hblank);
1700}
1701
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001702void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001703{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001704 if (statusblank > 1)
1705 statusblank--;
1706 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
1707 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001708 blank_statusbar();
1709 wnoutrefresh(bottomwin);
1710 reset_cursor();
1711 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001712 }
1713}
1714
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001715void blank_bottombars(void)
1716{
1717 if (!ISSET(NO_HELP)) {
1718 mvwaddstr(bottomwin, 1, 0, hblank);
1719 mvwaddstr(bottomwin, 2, 0, hblank);
1720 }
1721}
1722
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001723/* buf is a multibyte string to be displayed. We need to expand tabs
1724 * and control characters. How many bytes do we need to display buf
1725 * properly, not counting the null terminator? start_col is the column
1726 * of *buf (usually 0). We display to (end_col - 1). */
1727size_t display_string_len(const char *buf, size_t start_col, size_t
1728 end_col)
1729{
1730 size_t retval = 0;
1731
1732 assert(buf != NULL);
1733
1734 /* Throughout the loop, we maintain the fact that *buf displays at
1735 * column start_col. */
1736 while (start_col <= end_col && *buf != '\0') {
1737 int wide_buf;
1738 /* The current wide character. */
1739 int wide_buf_len;
1740 /* How many bytes wide is this character? */
1741 size_t old_col = start_col;
David Lawrence Ramsey9ec76e52004-12-23 19:55:57 +00001742#ifdef NANO_WIDE
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001743 bool bad_char;
David Lawrence Ramsey9ec76e52004-12-23 19:55:57 +00001744#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001745
1746 wide_buf_len = parse_char(buf, &wide_buf, &start_col
1747#ifdef NANO_WIDE
1748 , &bad_char
1749#endif
1750 );
1751
1752#ifdef NANO_WIDE
1753 /* If buf contains a null byte or an invalid multibyte
1754 * character, interpret its first byte as though it's a wide
1755 * character. */
1756 if (!ISSET(NO_UTF8) && bad_char) {
1757 char *bad_wide_buf = charalloc(MB_CUR_MAX);
1758 int bad_wide_buf_len;
1759
1760 /* If we have a control character, add one byte to account
1761 * for the "^" that will be displayed in front of it, and
1762 * translate the character to its visible equivalent as
1763 * returned by control_rep(). */
1764 if (is_cntrl_char(wide_buf)) {
1765 retval++;
1766 wide_buf = control_rep((unsigned char)wide_buf);
1767 }
1768
1769 /* Translate the wide character to its multibyte
1770 * equivalent. */
1771 bad_wide_buf_len = wctomb(bad_wide_buf, (wchar_t)wide_buf);
1772
1773 if (bad_wide_buf_len != -1)
1774 retval += bad_wide_buf_len;
1775
1776 free(bad_wide_buf);
1777 } else
1778#endif
1779 /* If we have a tab, get its width in bytes using the current
1780 * value of col. */
1781 if (wide_buf == '\t')
1782 retval += start_col - old_col;
1783 /* If we have a control character, add one byte to account for
1784 * the "^" that will be displayed in front of it, and translate
1785 * the byte to its visible equivalent as returned by
1786 * control_rep(). */
1787 else if (is_cntrl_char(wide_buf)) {
1788 char ctrl_wide_buf = control_rep((unsigned char)wide_buf);
1789
1790 retval += parse_char(&ctrl_wide_buf, NULL, NULL
1791#ifdef NANO_WIDE
1792 , NULL
1793#endif
1794 ) + 1;
1795
1796 /* If we have a normal character, add its width in bytes
1797 * normally. */
1798 } else
1799 retval += wide_buf_len;
1800 buf += wide_buf_len;
1801 }
1802
1803 return retval;
1804}
1805
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001806/* Convert buf into a string that can be displayed on screen. The
1807 * caller wants to display buf starting with column start_col, and
1808 * extending for at most len columns. start_col is zero-based. len is
1809 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001810 * string is dynamically allocated, and should be freed. If dollars is
1811 * TRUE, the caller might put "$" at the beginning or end of the line if
1812 * it's too long. */
1813char *display_string(const char *buf, size_t start_col, size_t len, bool
1814 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001815{
1816 size_t start_index;
1817 /* Index in buf of first character shown in return value. */
1818 size_t column;
1819 /* Screen column start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001820 size_t alloc_len;
1821 /* The length of memory allocated for converted. */
1822 char *converted;
1823 /* The string we return. */
1824 size_t index;
1825 /* Current position in converted. */
1826
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001827 /* If dollars is TRUE, make room for the "$" at the end of the
1828 * line. Also make sure that we don't try to display only part of a
1829 * multicolumn character there. */
1830 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
1831 len--;
1832
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001833 if (len == 0)
1834 return mallocstrcpy(NULL, "");
1835
1836 start_index = actual_x(buf, start_col);
1837 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001838
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001839 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001840
1841 alloc_len = display_string_len(buf + start_index, start_col,
1842 column + len) + 2;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001843 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001844 index = 0;
1845
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001846 if (column > start_col || (dollars && column > 0 &&
1847 buf[start_index] != '\t')) {
1848 int wide_buf, wide_buf_len;
1849
1850 /* We don't display all of buf[start_index] since it starts to
1851 * the left of the screen. */
1852 wide_buf_len = parse_char(buf + start_index, &wide_buf, NULL
1853#ifdef NANO_WIDE
1854 , NULL
1855#endif
1856 );
1857
1858 if (is_cntrl_char(wide_buf)) {
1859 if (column > start_col) {
1860 char *ctrl_wide_buf = charalloc(MB_CUR_MAX);
1861 int ctrl_wide_buf_len, i;
1862
1863 wide_buf = control_rep((unsigned char)wide_buf);
1864 ctrl_wide_buf_len = wctomb(ctrl_wide_buf,
1865 (wchar_t)wide_buf);
1866
1867 for (i = 0; i < ctrl_wide_buf_len; i++)
1868 converted[index++] = ctrl_wide_buf[i];
1869
1870 free(ctrl_wide_buf);
1871 start_index += wide_buf_len;
1872 }
1873 } else if (wcwidth(wide_buf) > 1) {
1874 /* If dollars is TRUE, make room for the "$" at the
1875 * beginning of the line. Also make sure that we don't try
1876 * to display only part of a multicolumn character there. */
1877 converted[0] = ' ';
1878 index = 1;
1879 if (dollars && column == start_col) {
1880 converted[1] = ' ';
1881 index = 2;
1882 }
1883 start_index += wide_buf_len;
1884 }
1885 }
1886
1887 while (index < alloc_len && buf[start_index] != '\0') {
1888 int wide_buf, wide_buf_len;
David Lawrence Ramsey9ec76e52004-12-23 19:55:57 +00001889#ifdef NANO_WIDE
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001890 bool bad_char;
David Lawrence Ramsey9ec76e52004-12-23 19:55:57 +00001891#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001892
1893 wide_buf_len = parse_char(buf + start_index, &wide_buf, NULL
1894#ifdef NANO_WIDE
1895 , &bad_char
1896#endif
1897 );
1898
1899#ifdef NANO_WIDE
1900 if (!ISSET(NO_UTF8) && bad_char) {
1901 char *bad_wide_buf = charalloc(MB_CUR_MAX);
1902 int bad_wide_buf_len, i;
1903
1904 if (is_cntrl_char(wide_buf)) {
1905 converted[index++] = '^';
1906 start_col++;
1907 wide_buf = control_rep((unsigned char)wide_buf);
1908 }
1909
1910 bad_wide_buf_len = wctomb(bad_wide_buf, (wchar_t)wide_buf);
1911
1912 for (i = 0; i < bad_wide_buf_len; i++)
1913 converted[index++] = bad_wide_buf[i];
1914
1915 free(bad_wide_buf);
1916
1917 start_col += wcwidth((wchar_t)wide_buf);
1918 } else
1919#endif
1920 if (wide_buf == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001921 converted[index++] =
1922#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
1923 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
1924#endif
1925 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001926 start_col++;
1927 while ((column + index) % tabsize) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001928 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001929 start_col++;
1930 }
1931 } else if (is_cntrl_char(wide_buf)) {
1932 char *ctrl_wide_buf = charalloc(MB_CUR_MAX);
1933 int ctrl_wide_buf_len, i;
1934
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001935 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001936 start_col++;
1937 wide_buf = control_rep((unsigned char)wide_buf);
1938
1939 ctrl_wide_buf_len = wctomb(ctrl_wide_buf,
1940 (wchar_t)wide_buf);
1941
1942 for (i = 0; i < ctrl_wide_buf_len; i++)
1943 converted[index++] = ctrl_wide_buf[i];
1944
1945 free(ctrl_wide_buf);
1946
1947 start_col += wcwidth((wchar_t)wide_buf);
1948 } else if (wide_buf == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001949 converted[index++] =
1950#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
1951 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
1952#endif
1953 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001954 start_col++;
1955 } else {
1956 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001957
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00001958 for (i = 0; i < wide_buf_len; i++)
1959 converted[index++] = buf[start_index + i];
1960
1961#ifdef NANO_WIDE
1962 if (!ISSET(NO_UTF8))
1963 start_col += wcwidth((wchar_t)wide_buf);
1964 else
1965#endif
1966 start_col++;
1967 }
1968
1969 start_index += wide_buf_len;
1970 }
1971
1972 /* Make sure that converted is at most len columns wide. */
1973 converted[index] = '\0';
1974 index = actual_x(converted, len);
1975 null_at(&converted, index);
1976
1977 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001978}
1979
Chris Allegretta7662c862003-01-13 01:35:15 +00001980/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001981 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00001982 *
Chris Allegretta7662c862003-01-13 01:35:15 +00001983 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00001984 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001985void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001986{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001987 size_t x_real = strnlenpt(inputbuf, x);
1988 int wid = COLS - strlen(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00001989
Chris Allegretta6df90f52002-07-19 01:08:59 +00001990 assert(0 <= x && x <= strlen(inputbuf));
1991
Chris Allegrettab3655b42001-10-22 03:15:31 +00001992 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001993 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001994
Chris Allegretta6df90f52002-07-19 01:08:59 +00001995 mvwaddstr(bottomwin, 0, 0, buf);
1996 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001997
1998 if (COLS > 1)
1999 waddch(bottomwin, x_real < wid ? ' ' : '$');
2000 if (COLS > 2) {
2001 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002002 char *expanded = display_string(inputbuf, page_start, wid,
2003 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002004
2005 assert(wid > 0);
2006 assert(strlen(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002007
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002008 waddstr(bottomwin, expanded);
2009 free(expanded);
2010 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2011 } else
2012 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002013 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002014}
2015
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002016/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002017 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002018int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002019#ifndef NANO_SMALL
2020 historyheadtype *history_list,
2021#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002022 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002023#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002024 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002025#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002026 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002027{
2028 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00002029 bool meta_key, func_key;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00002030 static size_t x = (size_t)-1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002031 /* the cursor position in 'answer' */
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00002032 size_t xend;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002033 /* length of 'answer', the status bar text */
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002034 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002035 /* used by input_tab() */
2036 const shortcut *t;
Chris Allegretta598106e2002-01-19 01:59:37 +00002037
Chris Allegretta5beed502003-01-05 20:41:21 +00002038#ifndef NANO_SMALL
2039 /* for history */
2040 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00002041 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00002042 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002043 int last_kbinput = 0;
2044
2045 /* This variable is used in the search history code. use_cb == 0
2046 means that we're using the existing history and ignoring
2047 currentbuf. use_cb == 1 means that the entry in answer should be
2048 moved to currentbuf or restored from currentbuf to answer.
2049 use_cb == 2 means that the entry in currentbuf should be moved to
2050 answer or restored from answer to currentbuf. */
2051 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002052#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00002053 xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002054
David Lawrence Ramsey4dd723a2004-10-05 02:29:52 +00002055 /* Only put x at the end of the string if it's uninitialized, if it
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002056 would be past the end of the string as it is, or if
2057 resetstatuspos is TRUE. Otherwise, leave it alone. This is so
2058 the cursor position stays at the same place if a prompt-changing
2059 toggle is pressed. */
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00002060 if (x == (size_t)-1 || x > xend || resetstatuspos)
Chris Allegretta09fc4302003-01-16 22:16:38 +00002061 x = xend;
2062
Chris Allegrettae1e0fd62003-04-15 01:15:09 +00002063 answer = charealloc(answer, xend + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002064 if (xend > 0)
2065 strcpy(answer, def);
2066 else
2067 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002068
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00002069#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002070 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002071#endif
2072
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002073 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00002074
Chris Allegretta6df90f52002-07-19 01:08:59 +00002075 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002076
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002077 /* Make sure any editor screen updates are displayed before getting
2078 input */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002079 wnoutrefresh(edit);
2080 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002081
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002082 /* If we're using restricted mode, we aren't allowed to change the
2083 * name of a file once it has one because that would allow writing
2084 * to files not specified on the command line. In this case,
2085 * disable all keys that would change the text if the filename isn't
2086 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00002087 while ((kbinput = get_kbinput(bottomwin, &meta_key, &func_key)) !=
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002088 NANO_CANCEL_KEY && kbinput != NANO_ENTER_KEY) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002089 for (t = s; t != NULL; t = t->next) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002090#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002091 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002092#endif
2093
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00002094 /* Temporary hack to interpret NANO_HELP_FKEY correctly. */
2095 if (kbinput == t->funcval)
2096 kbinput = t->ctrlval;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002097
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00002098 if (kbinput == t->ctrlval && is_cntrl_char(kbinput)) {
Chris Allegretta5bf51d32000-11-16 06:01:10 +00002099
Chris Allegrettab3655b42001-10-22 03:15:31 +00002100#ifndef DISABLE_HELP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002101 /* Have to do this here, it would be too late to do it
2102 in statusq() */
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002103 if (kbinput == NANO_HELP_KEY) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00002104 do_help();
2105 break;
2106 }
2107#endif
David Lawrence Ramseya593f532003-11-28 19:47:42 +00002108#ifndef NANO_SMALL
2109 /* Have to handle these here too, for the time being */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002110 if (kbinput == NANO_PREVLINE_KEY || kbinput == NANO_NEXTLINE_KEY)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00002111 break;
2112#endif
Chris Allegretta5af58892003-01-17 21:07:38 +00002113
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00002114 return t->ctrlval;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002115 }
2116 }
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00002117 assert(x <= xend && xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002118
Chris Allegretta04d848e2000-11-05 17:54:41 +00002119 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002120 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00002121
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002122 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00002123#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002124 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00002125 {
2126 int mouse_x, mouse_y;
2127 get_mouseinput(&mouse_x, &mouse_y, TRUE);
2128 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002129 break;
2130#endif
David Lawrence Ramsey72d8e542004-09-25 00:45:07 +00002131 case NANO_REFRESH_KEY:
2132 total_refresh();
2133 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00002134 case NANO_HOME_KEY:
David Lawrence Ramseyc7acf692004-05-22 20:15:20 +00002135#ifndef NANO_SMALL
2136 if (ISSET(SMART_HOME)) {
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00002137 size_t old_x = x;
David Lawrence Ramseyc7acf692004-05-22 20:15:20 +00002138
2139 for (x = 0; isblank(answer[x]) && x < xend; x++)
2140 ;
2141
2142 if (x == old_x || x == xend)
2143 x = 0;
2144 } else
2145#endif
2146 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002147 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00002148 case NANO_END_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00002149 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002150 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00002151 case NANO_FORWARD_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002152 if (x < xend)
2153 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002154 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002155 case NANO_DELETE_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002156 /* If we're using restricted mode, the filename isn't blank,
2157 * and we're at the "Write File" prompt, disable Delete. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00002158 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
2159 if (x < xend) {
2160 charmove(answer + x, answer + x + 1, xend - x);
2161 xend--;
2162 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002163 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002164 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002165 case NANO_CUT_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002166 /* If we're using restricted mode, the filename isn't blank,
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00002167 * and we're at the "Write File" prompt, disable Cut. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00002168 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
2169 null_at(&answer, 0);
2170 xend = 0;
2171 x = 0;
2172 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002173 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002174 case NANO_BACKSPACE_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002175 /* If we're using restricted mode, the filename isn't blank,
2176 * and we're at the "Write File" prompt, disable
2177 * Backspace. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00002178 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
2179 if (x > 0) {
2180 charmove(answer + x - 1, answer + x, xend - x + 1);
2181 x--;
2182 xend--;
2183 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002184 }
Chris Allegretta04d848e2000-11-05 17:54:41 +00002185 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002186 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002187#ifndef NANO_SMALL
2188 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00002189 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002190 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002191 history_list->current = (historytype *)history_list;
2192 history_list->len = strlen(answer);
2193 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002194
Chris Allegretta7662c862003-01-13 01:35:15 +00002195 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002196 complete = get_history_completion(history_list, answer);
2197 xend = strlen(complete);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002198 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002199 answer = mallocstrcpy(answer, complete);
2200 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002201 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002202#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002203 else
2204#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002205#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002206#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002207 if (allow_tabs) {
Chris Allegretta327abda2003-01-17 05:04:17 +00002208 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002209
Chris Allegretta327abda2003-01-17 05:04:17 +00002210 answer = input_tab(answer, x, &tabbed, &shift, list);
2211 xend = strlen(answer);
2212 x += shift;
2213 if (x > xend)
2214 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002215 }
2216#endif
2217 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00002218 case NANO_BACK_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00002219 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002220 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002221 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002222 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002223#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002224 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002225
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002226 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2227 isn't NULL, and currentbuf is different from answer,
2228 it means that we're scrolling up at the top of the
2229 search history, and we need to save the current
2230 answer in currentbuf; do this and reset use_cb to
2231 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002232 if (currentbuf == NULL || (use_cb == 1 &&
2233 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002234 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002235 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002236 }
2237
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002238 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2239 is different from answer, it means that we're
2240 scrolling up at the bottom of the search history, and
2241 we need to make the string in currentbuf the current
2242 answer; do this, blow away currentbuf since we don't
2243 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002244 if (currentbuf != NULL && use_cb == 2 &&
2245 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002246 answer = mallocstrcpy(answer, currentbuf);
2247 free(currentbuf);
2248 currentbuf = NULL;
2249 xend = strlen(answer);
2250 use_cb = 0;
2251
2252 /* else get older search from the history list and save
2253 it in answer; if there is no older search, blank out
2254 answer */
2255 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002256 answer = mallocstrcpy(answer, history);
2257 xend = strlen(history);
2258 } else {
2259 answer = mallocstrcpy(answer, "");
2260 xend = 0;
2261 }
2262 x = xend;
2263 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002264#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002265 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002266 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002267#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002268 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002269
2270 /* get newer search from the history list and save it
2271 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002272 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002273 answer = mallocstrcpy(answer, history);
2274 xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002275
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002276 /* if there is no newer search, we're here */
2277
2278 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2279 that we're scrolling down at the bottom of the search
2280 history and we need to make the string in currentbuf
2281 the current answer; do this, blow away currentbuf
2282 since we don't need it anymore, and set use_cb to
2283 1 */
2284 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002285 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002286 free(currentbuf);
2287 currentbuf = NULL;
2288 xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002289 use_cb = 1;
2290
2291 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2292 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002293 the search history and the current answer (if it's
2294 not blank) needs to be saved in currentbuf; do this,
2295 blank out answer (if necessary), and set use_cb to
2296 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002297 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002298 if (answer[0] != '\0') {
2299 currentbuf = mallocstrcpy(currentbuf, answer);
2300 answer = mallocstrcpy(answer, "");
2301 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002302 xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002303 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002304 }
2305 x = xend;
2306 }
2307#endif
2308 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00002309 default:
2310
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002311 for (t = s; t != NULL; t = t->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +00002312#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002313 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
Chris Allegretta598106e2002-01-19 01:59:37 +00002314 kbinput);
Chris Allegretta658399a2001-06-14 02:54:22 +00002315#endif
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002316 if (meta_key && (kbinput == t->metaval || kbinput == t->miscval))
David Lawrence Ramsey32613fa2004-05-24 18:40:41 +00002317 /* We hit a meta key. Do like above. We don't
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00002318 * just put back the letter and let it get
David Lawrence Ramsey82138502003-12-24 08:03:54 +00002319 * caught above cause that screws the
2320 * keypad... */
2321 return kbinput;
Chris Allegretta658399a2001-06-14 02:54:22 +00002322 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002323
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002324 /* If we're using restricted mode, the filename isn't blank,
2325 * and we're at the "Write File" prompt, act as though the
2326 * unhandled character we got is a control character and
2327 * throw it away. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00002328 if (is_cntrl_char(kbinput) || (ISSET(RESTRICTED) && filename[0] != '\0' && s == writefile_list))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002329 break;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002330 answer = charealloc(answer, xend + 2);
David Lawrence Ramsey9eff7462003-09-16 02:04:00 +00002331 charmove(answer + x + 1, answer + x, xend - x + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002332 xend++;
2333 answer[x] = kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002334 x++;
2335
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002336#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002337 fprintf(stderr, "input \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002338#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002339 } /* switch (kbinput) */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002340#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002341 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002342#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00002343 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002344 wrefresh(bottomwin);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002345 } /* while (kbinput ...) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002346
Chris Allegretta5af58892003-01-17 21:07:38 +00002347 /* We finished putting in an answer; reset x */
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00002348 x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002349
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002350 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002351}
2352
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002353/* Ask a question on the statusbar. Answer will be stored in answer
2354 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2355 * otherwise, the valid shortcut key caught. def is any editable text
2356 * we want to put up by default.
2357 *
2358 * New arg tabs tells whether or not to allow tab completion. */
2359int statusq(bool allow_tabs, const shortcut *s, const char *def,
2360#ifndef NANO_SMALL
2361 historyheadtype *which_history,
2362#endif
2363 const char *msg, ...)
2364{
2365 va_list ap;
2366 char *foo = charalloc(COLS - 3);
2367 int ret;
2368#ifndef DISABLE_TABCOMP
2369 bool list = FALSE;
2370#endif
2371
2372 bottombars(s);
2373
2374 va_start(ap, msg);
2375 vsnprintf(foo, COLS - 4, msg, ap);
2376 va_end(ap);
2377 foo[COLS - 4] = '\0';
2378
2379 ret = nanogetstr(allow_tabs, foo, def,
2380#ifndef NANO_SMALL
2381 which_history,
2382#endif
2383 s
2384#ifndef DISABLE_TABCOMP
2385 , &list
2386#endif
2387 );
2388 free(foo);
2389 resetstatuspos = FALSE;
2390
2391 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002392 case NANO_FIRSTLINE_KEY:
2393 case NANO_FIRSTLINE_FKEY:
2394 do_first_line();
2395 resetstatuspos = TRUE;
2396 break;
2397 case NANO_LASTLINE_KEY:
2398 case NANO_LASTLINE_FKEY:
2399 do_last_line();
2400 resetstatuspos = TRUE;
2401 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002402#ifndef DISABLE_JUSTIFY
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002403 case NANO_PARABEGIN_KEY:
2404 case NANO_PARABEGIN_ALTKEY1:
2405 case NANO_PARABEGIN_ALTKEY2:
2406 do_para_begin();
2407 resetstatuspos = TRUE;
2408 break;
2409 case NANO_PARAEND_KEY:
2410 case NANO_PARAEND_ALTKEY1:
2411 case NANO_PARAEND_ALTKEY2:
2412 do_para_end();
2413 resetstatuspos = TRUE;
2414 break;
2415 case NANO_FULLJUSTIFY_KEY:
2416 case NANO_FULLJUSTIFY_ALTKEY:
2417 if (!ISSET(VIEW_MODE))
2418 do_full_justify();
2419 resetstatuspos = TRUE;
2420 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002421#endif
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002422 case NANO_CANCEL_KEY:
2423 ret = -1;
2424 resetstatuspos = TRUE;
2425 break;
2426 case NANO_ENTER_KEY:
2427 ret = (answer[0] == '\0') ? -2 : 0;
2428 resetstatuspos = TRUE;
2429 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002430 }
2431 blank_statusbar();
2432
2433#ifdef DEBUG
2434 fprintf(stderr, "I got \"%s\"\n", answer);
2435#endif
2436
2437#ifndef DISABLE_TABCOMP
2438 /* if we've done tab completion, there might be a list of
2439 filename matches on the edit window at this point; make sure
2440 they're cleared off. */
2441 if (list)
2442 edit_refresh();
2443#endif
2444
2445 return ret;
2446}
2447
2448void statusq_abort(void)
2449{
2450 resetstatuspos = TRUE;
2451}
2452
Chris Allegrettaf717f982003-02-13 22:25:01 +00002453void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002454{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002455 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002456 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002457 size_t verlen = strlenpt(VERMSG) + 1;
2458 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002459 const char *prefix;
2460 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2461 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002462 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002463 const char *state;
2464 /* "Modified", "View", or spaces the length of "Modified".
2465 * Tells the state of this buffer. */
2466 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002467 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002468 char *exppath = NULL;
2469 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002470 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002471 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002472 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002473 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002474
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002475 assert(path != NULL || filename != NULL);
2476 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002477
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002478 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002479
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002480 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002481
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002482 if (COLS <= 5 || COLS - 5 < verlen)
2483 space = 0;
2484 else {
2485 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002486 /* Reserve 2/3 of the screen plus one column for after the
2487 * version message. */
2488 if (space < COLS - (COLS / 3) + 1)
2489 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002490 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002491
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002492 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002493 /* The version message should only take up 1/3 of the screen
2494 * minus one column. */
2495 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002496 waddstr(topwin, " ");
2497 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002498
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002499 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002500 state = _("Modified");
2501 else if (path == NULL && ISSET(VIEW_MODE))
2502 state = _("View");
2503 else {
2504 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002505 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002506 state = &hblank[COLS - statelen];
2507 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002508 statelen = strnlenpt(state, COLS);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002509 /* We need a space before state. */
2510 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2511 statelen++;
2512
2513 assert(space >= 0);
2514 if (space == 0 || statelen >= space)
2515 goto the_end;
2516
2517#ifndef DISABLE_BROWSER
2518 if (path != NULL)
2519 prefix = _("DIR:");
2520 else
2521#endif
2522 if (filename[0] == '\0') {
2523 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002524 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002525 } else
2526 prefix = _("File:");
2527 assert(statelen < space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002528 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002529 /* If newfie is FALSE, we need a space after prefix. */
2530 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002531 prefixlen++;
2532
2533 if (path == NULL)
2534 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002535 if (space >= prefixlen + statelen)
2536 space -= prefixlen + statelen;
2537 else
2538 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002539 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002540 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002541 size_t lenpt = strlenpt(path), start_col;
2542
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002543 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002544
2545 if (dots) {
2546 start_col = lenpt - space + 3;
2547 space -= 3;
2548 } else
2549 start_col = 0;
2550
2551 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002552 }
2553
2554 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002555 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2556 /* The length of the expanded filename. */
2557
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002558 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002559 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002560 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002561 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002562 assert(strlenpt(prefix) + 1 == prefixlen);
2563
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002564 waddch(topwin, ' ');
2565 waddstr(topwin, exppath);
2566 }
2567 } else {
2568 /* We will say something like "File: ...ename". */
2569 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002570 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002571 goto the_end;
2572 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002573 waddnstr(topwin, "...", space + 3);
2574 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002575 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002576 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002577 }
2578
2579 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002580 free(exppath);
2581
2582 if (COLS <= 1 || statelen >= COLS - 1)
2583 mvwaddnstr(topwin, 0, 0, state, COLS);
2584 else {
2585 assert(COLS - statelen - 2 >= 0);
2586 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2587 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2588 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002589
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002590 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002591
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002592 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002593 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002594 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002595}
2596
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002597/* If modified is not already set, set it and update titlebar. */
2598void set_modified(void)
2599{
2600 if (!ISSET(MODIFIED)) {
2601 SET(MODIFIED);
2602 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002603 }
2604}
2605
2606void statusbar(const char *msg, ...)
2607{
2608 va_list ap;
2609
2610 va_start(ap, msg);
2611
2612 /* Curses mode is turned off. If we use wmove() now, it will muck
2613 * up the terminal settings. So we just use vfprintf(). */
2614 if (curses_ended) {
2615 vfprintf(stderr, msg, ap);
2616 va_end(ap);
2617 return;
2618 }
2619
2620 /* Blank out the line. */
2621 blank_statusbar();
2622
2623 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002624 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002625 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002626#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002627 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002628
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002629 UNSET(WHITESPACE_DISPLAY);
2630#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002631 bar = charalloc(COLS - 3);
2632 vsnprintf(bar, COLS - 3, msg, ap);
2633 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002634 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002635#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2636 if (old_whitespace)
2637 SET(WHITESPACE_DISPLAY);
2638#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002639 free(bar);
2640 foo_len = strlen(foo);
2641 start_x = (COLS - foo_len - 4) / 2;
2642
2643 wmove(bottomwin, 0, start_x);
2644 wattron(bottomwin, A_REVERSE);
2645
2646 waddstr(bottomwin, "[ ");
2647 waddstr(bottomwin, foo);
2648 free(foo);
2649 waddstr(bottomwin, " ]");
2650 wattroff(bottomwin, A_REVERSE);
2651 wnoutrefresh(bottomwin);
2652 reset_cursor();
2653 wrefresh(edit);
2654 /* Leave the cursor at its position in the edit window, not
2655 * in the statusbar. */
2656 }
2657
2658 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002659 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002660}
2661
Chris Allegretta6232d662002-05-12 19:52:15 +00002662void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002663{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002664 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002665
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002666 if (ISSET(NO_HELP))
2667 return;
2668
Chris Allegretta6232d662002-05-12 19:52:15 +00002669 if (s == main_list) {
2670 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002671 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002672 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002673 slen = length_of_list(s);
2674
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002675 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002676 if (slen > MAIN_VISIBLE)
2677 slen = MAIN_VISIBLE;
2678 }
2679
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002680 /* There will be this many characters per column. We need at least
2681 * 3 to display anything properly.*/
2682 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002683
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002684 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002685
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002686 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002687 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002688
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002689 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002690#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002691 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002692 keystr = _("Up");
2693 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002694#endif
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002695 char foo[4];
Chris Allegretta658399a2001-06-14 02:54:22 +00002696
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002697 if (s->ctrlval == NANO_CONTROL_SPACE)
2698 strcpy(foo, "^ ");
2699 else if (s->ctrlval == NANO_CONTROL_8)
2700 strcpy(foo, "^?");
2701 /* Normal values. Assume that the shortcut has an
2702 * equivalent control key, meta key sequence, or both. */
2703 else if (s->ctrlval != NANO_NO_KEY)
2704 sprintf(foo, "^%c", s->ctrlval + 64);
2705 else if (s->metaval != NANO_NO_KEY)
2706 sprintf(foo, "M-%c", toupper(s->metaval));
2707
2708 keystr = foo;
2709#ifndef NANO_SMALL
2710 }
2711#endif
2712
2713 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002714 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002715 }
2716
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002717 wnoutrefresh(bottomwin);
2718 reset_cursor();
2719 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002720}
2721
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002722/* Write a shortcut key to the help area at the bottom of the window.
2723 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2724 * to write at most len characters, even if len is very small and
2725 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2726 * the whole string! We do not bother padding the entry with blanks. */
2727void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002728{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002729 assert(keystroke != NULL && desc != NULL && len >= 0);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002730 wattron(bottomwin, A_REVERSE);
2731 waddnstr(bottomwin, keystroke, len);
2732 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002733 len -= strlen(keystroke) + 1;
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002734 if (len > 0) {
2735 waddch(bottomwin, ' ');
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002736 waddnstr(bottomwin, desc, len);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002737 }
2738}
2739
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002740/* And so start the display update routines. */
2741
2742#ifndef NDEBUG
2743int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002744{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002745 int check_line = 0;
2746 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002747
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002748 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
2749 check_line++;
2750 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002751}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002752#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00002753
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002754/* nano scrolls horizontally within a line in chunks. This function
2755 * returns the column number of the first character displayed in the
2756 * window when the cursor is at the given column. Note that
2757 * 0 <= column - get_page_start(column) < COLS. */
2758size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002759{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002760 assert(COLS > 0);
2761 if (column == 0 || column < COLS - 1)
2762 return 0;
2763 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002764 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002765 else if (COLS > 2)
2766 return column - (COLS - 2);
2767 else
2768 return column - (COLS - 1);
2769 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002770}
2771
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002772/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002773 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002774void reset_cursor(void)
2775{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002776 /* If we haven't opened any files yet, put the cursor in the top
2777 * left corner of the edit window and get out. */
2778 if (edittop == NULL || current == NULL) {
2779 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002780 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002781 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002782
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002783 current_y = current->lineno - edittop->lineno;
2784 if (current_y < editwinrows) {
2785 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002786 wmove(edit, current_y, x - get_page_start(x));
2787 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002788}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002789
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002790/* edit_add() takes care of the job of actually painting a line into the
2791 * edit window. fileptr is the line to be painted, at row yval of the
2792 * window. converted is the actual string to be written to the window,
2793 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00002794 * characters. start is the column number of the first character of
2795 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002796 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002797void edit_add(const filestruct *fileptr, const char *converted, int
2798 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002799{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002800#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
2801 size_t startpos = actual_x(fileptr->data, start);
2802 /* The position in fileptr->data of the leftmost character
2803 * that displays at least partially on the window. */
2804 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2805 /* The position in fileptr->data of the first character that is
2806 * completely off the window to the right.
2807 *
2808 * Note that endpos might be beyond the null terminator of the
2809 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002810#endif
2811
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002812 assert(fileptr != NULL && converted != NULL);
2813 assert(strlen(converted) <= COLS);
2814
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002815 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002816 * just the text that needs it). */
2817 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002818
Chris Allegretta7dd77682001-12-08 19:52:28 +00002819#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00002820 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002821 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002822
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002823 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2824 int x_start;
2825 /* Starting column for mvwaddnstr. Zero-based. */
2826 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002827 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002828 * characters on a whole line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002829 regmatch_t startmatch; /* match position for start_regexp */
2830 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002831
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002832 if (tmpcolor->bright)
2833 wattron(edit, A_BOLD);
2834 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002835 /* Two notes about regexec(). Return value 0 means there is
2836 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002837 * after the match. */
2838
2839 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002840 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002841 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002842
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002843 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002844 * last match. Even though two matches may overlap, we
2845 * want to ignore them, so that we can highlight
2846 * C-strings correctly. */
2847 while (k < endpos) {
2848 /* Note the fifth parameter to regexec(). It says
2849 * not to match the beginning-of-line character
2850 * unless k is 0. If regexec() returns REG_NOMATCH,
2851 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00002852 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002853 &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002854 break;
2855 /* Translate the match to the beginning of the line. */
2856 startmatch.rm_so += k;
2857 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002858 if (startmatch.rm_so == startmatch.rm_eo) {
2859 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00002860 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002861 } else if (startmatch.rm_so < endpos &&
2862 startmatch.rm_eo > startpos) {
2863 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002864 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002865 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002866 x_start = strnlenpt(fileptr->data,
2867 startmatch.rm_so) - start;
2868 paintlen = strnlenpt(fileptr->data,
2869 startmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002870 if (paintlen > COLS - x_start)
2871 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002872
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002873 assert(0 <= x_start && 0 < paintlen &&
2874 x_start + paintlen <= COLS);
2875 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002876 converted + x_start, paintlen);
2877 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002878 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002879 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002880 } else {
2881 /* This is a multi-line regexp. There are two steps.
2882 * First, we have to see if the beginning of the line is
2883 * colored by a start on an earlier line, and an end on
2884 * this line or later.
2885 *
2886 * We find the first line before fileptr matching the
2887 * start. If every match on that line is followed by an
2888 * end, then go to step two. Otherwise, find the next line
2889 * after start_line matching the end. If that line is not
2890 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002891
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002892 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002893 /* the first line before fileptr matching start */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002894 regoff_t start_col;
2895 /* where it starts in that line */
2896 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002897
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002898 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00002899 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002900 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002901 /* If there is an end on this line, there is no need
2902 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002903 if (regexec(tmpcolor->end, start_line->data, 0,
2904 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002905 goto step_two;
2906 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002907 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002908 /* No start found, so skip to the next step. */
2909 if (start_line == NULL)
2910 goto step_two;
2911 /* Now start_line is the first line before fileptr
2912 * containing a start match. Is there a start on this
2913 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002914
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002915 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002916 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002917 start_col += startmatch.rm_so;
2918 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002919 if (regexec(tmpcolor->end,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002920 start_line->data + start_col + startmatch.rm_eo,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002921 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
2922 REG_NOTBOL) == REG_NOMATCH)
2923 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002924 break;
2925 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002926 if (regexec(&tmpcolor->start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002927 start_line->data + start_col, 1,
2928 &startmatch, REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002929 /* No later start on this line. */
2930 goto step_two;
2931 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002932 /* Indeed, there is a start not followed on this line by
2933 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002934
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002935 /* We have already checked that there is no end before
2936 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002937 * the start at all? We don't paint unterminated
2938 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002939 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002940 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00002941 regexec(tmpcolor->end, end_line->data, 1,
2942 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002943 end_line = end_line->next;
2944
2945 /* No end found, or it is too early. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002946 if (end_line == NULL ||
2947 (end_line == fileptr && endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002948 goto step_two;
2949
2950 /* Now paint the start of fileptr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002951 paintlen = end_line != fileptr ? COLS :
2952 strnlenpt(fileptr->data, endmatch.rm_eo) - start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002953 if (paintlen > COLS)
2954 paintlen = COLS;
2955
2956 assert(0 < paintlen && paintlen <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002957 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002958
2959 /* We have already painted the whole line. */
2960 if (paintlen == COLS)
2961 goto skip_step_two;
2962
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002963 step_two:
2964 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002965 start_col = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002966 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002967 if (regexec(&tmpcolor->start,
2968 fileptr->data + start_col, 1, &startmatch,
2969 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
2970 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002971 /* No more starts on this line. */
2972 break;
2973 /* Translate the match to be relative to the
2974 * beginning of the line. */
2975 startmatch.rm_so += start_col;
2976 startmatch.rm_eo += start_col;
2977
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002978 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002979 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002980 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002981 x_start = strnlenpt(fileptr->data,
2982 startmatch.rm_so) - start;
2983 if (regexec(tmpcolor->end,
2984 fileptr->data + startmatch.rm_eo, 1, &endmatch,
2985 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002986 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002987 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002988 endmatch.rm_so += startmatch.rm_eo;
2989 endmatch.rm_eo += startmatch.rm_eo;
2990 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002991 * appear on this page, and is the match more
2992 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002993 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002994 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002995 paintlen = strnlenpt(fileptr->data,
2996 endmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002997 if (x_start + paintlen > COLS)
2998 paintlen = COLS - x_start;
2999
3000 assert(0 <= x_start && 0 < paintlen &&
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003001 x_start + paintlen <= COLS);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003002 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003003 converted + x_start, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003004 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003005 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003006 /* There is no end on this line. But we haven't
3007 * yet looked for one on later lines. */
3008 end_line = fileptr->next;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003009 while (end_line != NULL &&
3010 regexec(tmpcolor->end, end_line->data, 0,
3011 NULL, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003012 end_line = end_line->next;
3013 if (end_line != NULL) {
3014 assert(0 <= x_start && x_start < COLS);
3015 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003016 converted + x_start, COLS - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003017 /* We painted to the end of the line, so
3018 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003019 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003020 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003021 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003022 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003023 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003024 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003025
Chris Allegrettace452fb2003-02-03 02:56:44 +00003026 skip_step_two:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003027 wattroff(edit, A_BOLD);
3028 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
3029 } /* for tmpcolor in colorstrings */
3030 }
Chris Allegretta598106e2002-01-19 01:59:37 +00003031#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003032
Chris Allegretta7dd77682001-12-08 19:52:28 +00003033#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003034 if (ISSET(MARK_ISSET)
3035 && (fileptr->lineno <= mark_beginbuf->lineno
3036 || fileptr->lineno <= current->lineno)
3037 && (fileptr->lineno >= mark_beginbuf->lineno
3038 || fileptr->lineno >= current->lineno)) {
3039 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003040
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003041 const filestruct *top;
3042 /* Either current or mark_beginbuf, whichever is first. */
3043 size_t top_x;
3044 /* current_x or mark_beginx, corresponding to top. */
3045 const filestruct *bot;
3046 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003047 int x_start;
3048 /* Starting column for mvwaddnstr. Zero-based. */
3049 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003050 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003051 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003052
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003053 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003054
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003055 if (top->lineno < fileptr->lineno || top_x < startpos)
3056 top_x = startpos;
3057 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3058 bot_x = endpos;
3059
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003060 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003061 if (top_x < endpos && bot_x > startpos) {
3062 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003063
3064 /* x_start is the expanded location of the beginning of the
3065 * mark minus the beginning of the page. */
3066 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003067
3068 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003069 /* If the end of the mark is off the page, paintlen is
3070 * -1, meaning that everything on the line gets
3071 * painted. */
3072 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003073 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003074 /* Otherwise, paintlen is the expanded location of the
3075 * end of the mark minus the expanded location of the
3076 * beginning of the mark. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003077 paintlen = strnlenpt(fileptr->data, bot_x)
3078 - (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003079
3080 /* If x_start is before the beginning of the page, shift
3081 * paintlen x_start characters to compensate, and put
3082 * x_start at the beginning of the page. */
3083 if (x_start < 0) {
3084 paintlen += x_start;
3085 x_start = 0;
3086 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003087
3088 assert(x_start >= 0 && x_start <= strlen(converted));
3089
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003090 wattron(edit, A_REVERSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003091 mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003092 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003093 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003094 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003095#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003096}
3097
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003098/* Just update one line in the edit buffer. This is basically a wrapper
3099 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003100 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003101 * If fileptr != current, then index is considered 0. The line will be
3102 * displayed starting with fileptr->data[index]. Likely args are
3103 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003104void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003105{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003106 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003107 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003108 char *converted;
3109 /* fileptr->data converted to have tabs and control characters
3110 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003111 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003112
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003113 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003114
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003115 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003116
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003117 /* We assume the line numbers are valid. Is that really true? */
3118 assert(line < 0 || line == check_linenumbers(fileptr));
3119
3120 if (line < 0 || line >= editwinrows)
3121 return;
3122
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003123 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003124 mvwaddstr(edit, line, 0, hblank);
3125
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003126 /* Next, convert variables that index the line to their equivalent
3127 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003128 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003129 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003130
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003131 /* Expand the line, replacing tabs with spaces, and control
3132 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003133 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003134
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003135 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003136 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003137 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003138
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003139 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003140 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003141 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003142 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003143}
3144
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003145/* Return a nonzero value if we need an update after moving
3146 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003147 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003148int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003149{
3150 return
3151#ifndef NANO_SMALL
3152 ISSET(MARK_ISSET) ||
3153#endif
3154 get_page_start(old_pww) != get_page_start(placewewant);
3155}
3156
3157/* Return a nonzero value if we need an update after moving vertically.
3158 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003159 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003160int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003161{
3162 return
3163#ifndef NANO_SMALL
3164 ISSET(MARK_ISSET) ||
3165#endif
3166 get_page_start(old_pww) != get_page_start(placewewant);
3167}
3168
3169/* Scroll the edit window in the given direction and the given number
3170 * of lines, and draw new lines on the blank lines left after the
3171 * scrolling. direction is the direction to scroll, either UP or DOWN,
3172 * and nlines is the number of lines to scroll. Don't redraw the old
3173 * topmost or bottommost line (where we assume current is) before
3174 * scrolling or draw the new topmost or bottommost line after scrolling
3175 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003176 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003177void edit_scroll(updown direction, int nlines)
3178{
3179 filestruct *foo;
3180 int i, scroll_rows = 0;
3181
3182 /* Scrolling less than one line or more than editwinrows lines is
3183 * redundant, so don't allow it. */
3184 if (nlines < 1 || nlines > editwinrows)
3185 return;
3186
3187 /* Move the top line of the edit window up or down (depending on the
3188 * value of direction) nlines lines. If there are fewer lines of
3189 * text than that left, move it to the top or bottom line of the
3190 * file (depending on the value of direction). Keep track of
3191 * how many lines we moved in scroll_rows. */
3192 for (i = nlines; i > 0; i--) {
3193 if (direction == UP) {
3194 if (edittop->prev == NULL)
3195 break;
3196 edittop = edittop->prev;
3197 scroll_rows--;
3198 } else {
3199 if (edittop->next == NULL)
3200 break;
3201 edittop = edittop->next;
3202 scroll_rows++;
3203 }
3204 }
3205
3206 /* Scroll the text on the screen up or down scroll_rows lines,
3207 * depending on the value of direction. */
3208 scrollok(edit, TRUE);
3209 wscrl(edit, scroll_rows);
3210 scrollok(edit, FALSE);
3211
3212 foo = edittop;
3213 if (direction != UP) {
3214 int slines = editwinrows - nlines;
3215 for (; slines > 0 && foo != NULL; slines--)
3216 foo = foo->next;
3217 }
3218
3219 /* And draw new lines on the blank top or bottom lines of the edit
3220 * window, depending on the value of direction. Don't draw the new
3221 * topmost or new bottommost line. */
3222 while (scroll_rows != 0 && foo != NULL) {
3223 if (foo->next != NULL)
3224 update_line(foo, 0);
3225 if (direction == UP)
3226 scroll_rows++;
3227 else
3228 scroll_rows--;
3229 foo = foo->next;
3230 }
3231}
3232
3233/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003234 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003235void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003236{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003237 int do_refresh = need_vertical_update(0) ||
3238 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003239 const filestruct *foo;
3240
3241 /* If either old_current or current is offscreen, refresh the screen
3242 * and get out. */
3243 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3244 edittop->lineno + editwinrows || current->lineno <
3245 edittop->lineno || current->lineno >= edittop->lineno +
3246 editwinrows) {
3247 edit_refresh();
3248 return;
3249 }
3250
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003251 /* Update old_current and current if we're not on the first page
3252 * and/or we're not on the same page as before. If the mark is on,
3253 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003254 foo = old_current;
3255 while (foo != current) {
3256 if (do_refresh)
3257 update_line(foo, 0);
3258#ifndef NANO_SMALL
3259 if (!ISSET(MARK_ISSET))
3260#endif
3261 break;
3262 if (foo->lineno > current->lineno)
3263 foo = foo->prev;
3264 else
3265 foo = foo->next;
3266 }
3267 if (do_refresh)
3268 update_line(current, current_x);
3269}
3270
Chris Allegretta6df90f52002-07-19 01:08:59 +00003271/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003272void edit_refresh(void)
3273{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003274 if (current->lineno < edittop->lineno ||
3275 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003276 /* Note that edit_update() changes edittop so that it's in range
3277 * of current. Thus, when it then calls edit_refresh(), there
3278 * is no danger of getting an infinite loop. */
3279 edit_update(
3280#ifndef NANO_SMALL
3281 ISSET(SMOOTHSCROLL) ? NONE :
3282#endif
3283 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003284 else {
3285 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003286 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003287
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003288#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003289 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003290#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003291
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003292 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003293 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003294 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003295 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003296 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003297 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003298 }
3299 while (nlines < editwinrows) {
3300 mvwaddstr(edit, nlines, 0, hblank);
3301 nlines++;
3302 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003303 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003304 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003305 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003306}
3307
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003308/* A nice generic routine to update the edit buffer. We keep current in
3309 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003310void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003311{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003312 filestruct *foo = current;
3313
Chris Allegretta6df90f52002-07-19 01:08:59 +00003314 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003315 /* If location is CENTER, we move edittop up (editwinrows / 2)
3316 * lines. This puts current at the center of the screen. If
3317 * location is NONE, we move edittop up current_y lines if
3318 * current_y is in range of the screen, 0 lines if current_y is
3319 * less than 0, or (editwinrows - 1) lines if current_y is
3320 * greater than (editwinrows - 1). This puts current at the
3321 * same place on the screen as before, or at the top or bottom
3322 * of the screen if edittop is beyond either. */
3323 int goal;
3324
3325 if (location == CENTER)
3326 goal = editwinrows / 2;
3327 else {
3328 goal = current_y;
3329
3330 /* Limit goal to (editwinrows - 1) lines maximum. */
3331 if (goal > editwinrows - 1)
3332 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003333 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003334
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003335 for (; goal > 0 && foo->prev != NULL; goal--)
3336 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003337 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003338
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003339 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003340 edit_refresh();
3341}
3342
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003343/* Ask a simple yes/no question, specified in msg, on the statusbar.
3344 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3345 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003346int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003347{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003348 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003349 const char *yesstr; /* String of yes characters accepted. */
3350 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003351 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003352
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003353 /* yesstr, nostr, and allstr are strings of any length. Each string
3354 * consists of all characters accepted as a valid character for that
3355 * value. The first value will be the one displayed in the
3356 * shortcuts. Translators: if possible, specify both the shortcuts
3357 * for your language and English. For example, in French: "OoYy"
3358 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003359 yesstr = _("Yy");
3360 nostr = _("Nn");
3361 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003362
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003363 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003364 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003365
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003366 if (COLS < 32)
3367 width = COLS / 2;
3368
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003369 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003370 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003371
Chris Allegretta6232d662002-05-12 19:52:15 +00003372 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003373 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003374 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003375
3376 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003377 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003378 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003379 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003380 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003381
Chris Allegrettadb28e962003-01-28 01:23:40 +00003382 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003383 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003384 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003385
Chris Allegrettadb28e962003-01-28 01:23:40 +00003386 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003387 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003388 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003389
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003390 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003391
3392 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003393 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003394
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003395 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003396
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003397 wrefresh(bottomwin);
3398
Chris Allegrettadb28e962003-01-28 01:23:40 +00003399 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003400 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003401 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003402#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003403 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003404#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003405
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003406 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003407
3408 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003409 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003410#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003411 /* Look, ma! We get to duplicate lots of code from
3412 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003413 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003414 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003415
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003416 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003417 wenclose(bottomwin, mouse_y, mouse_x) &&
3418 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003419 int x = mouse_x / width;
3420 /* Did we click in the first column of shortcuts, or
3421 * the second? */
3422 int y = mouse_y - editwinrows - 3;
3423 /* Did we click in the first row of shortcuts? */
3424
3425 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3426
3427 /* x = 0 means they clicked Yes or No.
3428 * y = 0 means Yes or All. */
3429 ok = -2 * x * y + x - y + 1;
3430
3431 if (ok == 2 && !all)
3432 ok = -2;
3433 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003434 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003435#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003436 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003437 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003438 else if (strchr(yesstr, kbinput) != NULL)
3439 ok = 1;
3440 else if (strchr(nostr, kbinput) != NULL)
3441 ok = 0;
3442 else if (all && strchr(allstr, kbinput) != NULL)
3443 ok = 2;
3444 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003445
Chris Allegrettadb28e962003-01-28 01:23:40 +00003446 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003447}
3448
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003449void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003450{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003451 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003452 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003453 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003454 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003455 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003456 wnoutrefresh(bottomwin);
3457 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003458 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003459 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003460 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003461 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003462 edit_refresh();
3463 /* FIXME: bottomwin needs to be refreshed too. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003464}
3465
3466void display_main_list(void)
3467{
3468 bottombars(main_list);
3469}
3470
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003471/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3472 * display the cursor position. Otherwise, we display it only if the
3473 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003474 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003475 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3476 * old_i and old_totsize. That way, we leave the current statusbar
3477 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003478void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003479{
Chris Allegrettad26ab912003-01-28 01:16:47 +00003480 const filestruct *fileptr;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003481 size_t i = 0;
3482 static size_t old_i = 0;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003483 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003484
Chris Allegrettad26ab912003-01-28 01:16:47 +00003485 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003486
3487 if (old_totsize == -1)
3488 old_totsize = totsize;
3489
Chris Allegrettad26ab912003-01-28 01:16:47 +00003490 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
3491 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003492 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003493 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003494 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003495
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003496 /* Check whether totsize is correct. Else there is a bug
3497 * somewhere. */
3498 assert(current != filebot || i == totsize);
3499
Chris Allegrettad26ab912003-01-28 01:16:47 +00003500 if (constant && ISSET(DISABLE_CURPOS)) {
3501 UNSET(DISABLE_CURPOS);
3502 old_i = i;
3503 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003504 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003505 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003506
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003507 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003508 * unconditionally; otherwise, only display the position when the
3509 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003510 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003511 size_t xpt = xplustabs() + 1;
3512 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003513 int linepct = 100 * current->lineno / totlines;
3514 int colpct = 100 * xpt / cur_len;
3515 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
3516
3517 statusbar(
3518 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3519 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003520 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003521 (unsigned long)i, totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003522 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003523 }
3524
3525 old_i = i;
3526 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003527}
3528
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003529void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003530{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003531 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003532}
3533
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003534#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003535/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003536int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003537{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003538 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003539
3540 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3541 ptr++;
3542 j++;
3543 }
3544 if (j == COLS - 5) {
3545 /* Don't wrap at the first of two spaces following a period. */
3546 if (*ptr == ' ' && *(ptr + 1) == ' ')
3547 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003548 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003549 while (*ptr != ' ' && j > 0) {
3550 ptr--;
3551 j--;
3552 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003553 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003554 if (j == 0)
3555 j = COLS - 5;
3556 }
3557 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
3558 return j;
3559}
3560
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003561/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003562void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003563{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003564 int line = 0;
3565 /* The line number in help_text of the first displayed help line.
3566 * This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003567 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003568 /* no_more means the end of the help text is shown, so don't go
3569 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003570 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003571 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003572
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003573 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003574#ifndef DISABLE_MOUSE
3575 const shortcut *oldshortcut = currshortcut;
3576 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003577 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003578#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003579
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003580 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003581 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003582 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003583 blank_statusbar();
3584
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003585 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003586 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003587 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003588
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003589#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003590 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003591 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003592 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003593#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003594
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003595 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003596 /* Make sure that the help screen's shortcut list will actually
3597 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003598 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003599 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003600 }
3601 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003602
3603 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003604 int i;
3605 int old_line = line;
3606 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003607 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003608
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003609 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003610#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003611 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003612 {
3613 int mouse_x, mouse_y;
3614 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3615 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003616 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003617#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003618 case NANO_NEXTPAGE_KEY:
3619 case NANO_NEXTPAGE_FKEY:
3620 if (!no_more)
3621 line += editwinrows - 2;
3622 break;
3623 case NANO_PREVPAGE_KEY:
3624 case NANO_PREVPAGE_FKEY:
3625 if (line > 0) {
3626 line -= editwinrows - 2;
3627 if (line < 0)
3628 line = 0;
3629 }
3630 break;
3631 case NANO_PREVLINE_KEY:
3632 if (line > 0)
3633 line--;
3634 break;
3635 case NANO_NEXTLINE_KEY:
3636 if (!no_more)
3637 line++;
3638 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003639 }
3640
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003641 if (line == old_line && kbinput != ERR)
3642 goto skip_redisplay;
3643
3644 blank_edit();
3645
3646 assert(COLS > 5);
3647
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003648 /* Calculate where in the text we should be, based on the
3649 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003650 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003651 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003652 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003653 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003654 }
3655
Chris Allegretta4640fe32003-02-10 03:10:03 +00003656 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003657 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003658
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003659 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003660 ptr += j;
3661 if (*ptr == '\n')
3662 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003663 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003664 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003665
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003666 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003667 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003668 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3669 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003670
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003671#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003672 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003673#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003674
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003675 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003676 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003677 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003678 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003679 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003680 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003681 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003682
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003683 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003684 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003685
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003686 /* The help_init() at the beginning allocated help_text. Since
3687 * help_text has now been written to the screen, we don't need it
3688 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003689 free(help_text);
3690 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003691}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003692#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003693
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003694/* Highlight the current word being replaced or spell checked. We
3695 * expect word to have tabs and control characters expanded. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003696void do_replace_highlight(int highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003697{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003698 size_t y = xplustabs();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003699 size_t word_len = strlen(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003700
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003701 y = get_page_start(y) + COLS - y;
3702 /* Now y is the number of characters we can display on this
3703 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003704
3705 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003706
Chris Allegrettafb62f732000-12-05 11:36:41 +00003707 if (highlight_flag)
3708 wattron(edit, A_REVERSE);
3709
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003710#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003711 /* This is so we can show zero-length regexes. */
3712 if (word_len == 0)
3713 waddstr(edit, " ");
3714 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003715#endif
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003716 waddnstr(edit, word, y - 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003717
3718 if (word_len > y)
3719 waddch(edit, '$');
3720 else if (word_len == y)
3721 waddch(edit, word[word_len - 1]);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003722
3723 if (highlight_flag)
3724 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003725}
3726
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003727#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003728/* Dump the passed-in file structure to stderr. */
3729void dump_buffer(const filestruct *inptr)
3730{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003731 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003732 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003733 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003734 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003735 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003736 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003737
3738 while (inptr != NULL) {
3739 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
3740 inptr = inptr->next;
3741 }
3742}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003743
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003744/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00003745void dump_buffer_reverse(void)
3746{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003747 const filestruct *fileptr = filebot;
3748
3749 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00003750 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003751 fileptr = fileptr->prev;
3752 }
3753}
3754#endif /* DEBUG */
3755
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003756#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003757#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003758#define XLCREDIT_LEN 8
3759
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00003760/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003761void do_credits(void)
3762{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003763 int crpos = 0, xlpos = 0;
3764 const char *credits[CREDIT_LEN] = {
3765 NULL, /* "The nano text editor" */
3766 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003767 VERSION,
3768 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003769 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003770 "Chris Allegretta",
3771 "Jordi Mallach",
3772 "Adam Rogoyski",
3773 "Rob Siemborski",
3774 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003775 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003776 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00003777 "Ken Tyler",
3778 "Sven Guckes",
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003779#ifdef NANO_WIDE
3780 !ISSET(NO_UTF8) ? "Florian K\xC3\xB6nig" :
3781#endif
3782 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00003783 "Pauli Virtanen",
3784 "Daniele Medri",
3785 "Clement Laforet",
3786 "Tedi Heriyanto",
3787 "Bill Soudan",
3788 "Christian Weisgerber",
3789 "Erik Andersen",
3790 "Big Gaute",
3791 "Joshua Jensen",
3792 "Ryan Krebs",
3793 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003794 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003795 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003796 "Plattsburgh State University",
3797 "Benet Laboratories",
3798 "Amy Allegretta",
3799 "Linda Young",
3800 "Jeremy Robichaud",
3801 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003802 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003803 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003804 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003805 "Thomas Dickey",
3806 "Pavel Curtis",
3807 "Zeyd Ben-Halim",
3808 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003809 NULL, /* "and anyone else we forgot..." */
3810 NULL, /* "Thank you for using nano!" */
3811 "",
3812 "",
3813 "",
3814 "",
David Lawrence Ramsey6481c3f2004-01-09 23:06:54 +00003815 "(c) 1999-2004 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003816 "",
3817 "",
3818 "",
3819 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003820 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003821 };
3822
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003823 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003824 N_("The nano text editor"),
3825 N_("version"),
3826 N_("Brought to you by:"),
3827 N_("Special thanks to:"),
3828 N_("The Free Software Foundation"),
3829 N_("For ncurses:"),
3830 N_("and anyone else we forgot..."),
3831 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003832 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003833
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003834 curs_set(0);
3835 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003836 scrollok(edit, TRUE);
3837 blank_titlebar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003838 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003839 blank_statusbar();
3840 blank_bottombars();
3841 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003842 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003843 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003844
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003845 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
3846 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003847 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003848 if (crpos < CREDIT_LEN) {
3849 const char *what = credits[crpos];
3850 size_t start_x;
3851
3852 if (what == NULL) {
3853 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00003854 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003855 xlpos++;
3856 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003857 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramseyeb711b02004-12-05 22:24:39 +00003858 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x,
3859 what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003860 }
3861 napms(700);
3862 scroll(edit);
3863 wrefresh(edit);
3864 if (wgetch(edit) != ERR)
3865 break;
3866 napms(700);
3867 scroll(edit);
3868 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003869 }
3870
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003871 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003872 nodelay(edit, FALSE);
3873 curs_set(1);
3874 display_main_list();
3875 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003876}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003877#endif