blob: e09e74367d91ed98bf8f2def6be34be8d4b983be [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
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000022#include "config.h"
23
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000024#include <stdarg.h>
25#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000026#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000027#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000028#include <ctype.h>
Chris Allegretta6232d662002-05-12 19:52:15 +000029#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000030#include "proto.h"
31#include "nano.h"
32
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000033static int statblank = 0; /* Number of keystrokes left after
Chris Allegretta88520c92001-05-05 17:45:54 +000034 we call statusbar(), before we
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000035 actually blank the statusbar */
Robert Siemborskid8510b22000-06-06 23:04:06 +000036
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000037/* Control character compatibility:
38 *
39 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
40 * VT100, and VT220.
41 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
42 * VT220, and VT320.
43 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
44 * VT220, and VT320.
45 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
46 * VT220, and VT320.
47 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
48 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000049 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000050 * ANSI, VT100, and VT220, and which is Backspace under VT320.
51 *
52 * Note: VT220s and VT320s also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000053 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
54 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000055 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000056 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000057 * on which the VT320 sequences are translated by the keypad to KEY_DC
58 * and [nothing]. We work around this conflict via the REBIND_DELETE
59 * flag: if it's not set, we assume VT320 compatibility, and if it is,
60 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
61 * Hemel for helping work this conflict out.
62 *
63 * Escape sequence compatibility:
64 *
65 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
66 * console, the FreeBSD console, the Hurd console (a.k.a. the Mach
67 * console), xterm, rxvt, and Eterm. Among these, there are several
68 * conflicts and omissions, outlined as follows:
69 *
70 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
71 * (Ctrl-I is also Tab on ANSI, which we already support.)
72 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
73 * NumLock off on Linux console; the latter is omitted. (The editing
74 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000075 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000076 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
77 * latter is omitted. (Mouse input will only work properly if the
78 * extended keypad value KEY_MOUSE is generated on mouse events
79 * instead of the escape sequence.)
80 * - F9 on FreeBSD console == PageDown on Hurd console; the former is
81 * omitted. (The editing keypad is more important to have working
82 * than the function keys, because the functions of the former are not
83 * arbitrary and the functions of the latter are.)
84 * - F10 on FreeBSD console == PageUp on Hurd console; the former is
85 * omitted. (Same as above.)
86 * - F13 on FreeBSD console == End on Hurd console; the former is
87 * omitted. (Same as above.)
88 * - The Hurd console has no escape sequences for F11, F12, F13, F14, or
89 * Center (5) on the numeric keypad with NumLock off.
90 *
91 * Note that Center (5) on the numeric keypad with NumLock off can also
92 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +000093
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000094#ifndef NANO_SMALL
95/* Reset all the input routines that rely on character sequences. */
96void reset_kbinput(void)
97{
98 get_translated_kbinput(0, NULL, TRUE);
99 get_ascii_kbinput(0, 0, TRUE);
100 get_untranslated_kbinput(0, 0, FALSE, TRUE);
101}
102#endif
103
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000104/* Read in a single input character. If it's ignored, swallow it and go
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000105 * on. Otherwise, try to translate it from ASCII, extended keypad
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000106 * values, and/or escape sequences. Set meta_key to TRUE when we get a
107 * meta sequence. Supported extended keypad values consist of [arrow
108 * key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace, the
109 * editing keypad (Insert, Delete, Home, End, PageUp, and PageDown), the
110 * function keypad (F1-F14), and the numeric keypad with NumLock off.
111 * Assume nodelay(win) is FALSE. */
David Lawrence Ramsey1576d532004-03-19 21:46:34 +0000112int get_kbinput(WINDOW *win, int *meta_key)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000113{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000114 int kbinput, es, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000115
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000116#ifndef NANO_SMALL
117 allow_pending_sigwinch(TRUE);
118#endif
119
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000120 *meta_key = FALSE;
121
122 while (retval == ERR) {
123 /* Read a character using blocking input, since using
124 * non-blocking input will eat up all unused CPU. Then pass it
125 * to get_translated_kbinput(). Continue until we get a
126 * complete sequence. */
127 kbinput = wgetch(win);
128 retval = get_translated_kbinput(kbinput, &es
129#ifndef NANO_SMALL
130 , FALSE
131#endif
132 );
133
134 /* If we got an escape sequence, read it in, including the
135 * initial non-escape, as verbatim input. */
136 if (es) {
137 int *escape_seq = NULL;
138 size_t es_len;
139
140 /* First, assume that we got a meta sequence. Set meta_key
141 * to TRUE and save the character we got as the result. We
142 * do this so that if there's a delay greater than nodelay()
143 * between Escape and the character we got (after we
144 * ungetch() it below), it'll still be properly interpreted
145 * as a meta sequence. */
146 *meta_key = TRUE;
147 retval = tolower(kbinput);
148
149 /* Next, send back the character we got and read in the
150 * complete escape sequence. */
151 ungetch(kbinput);
152 escape_seq = get_verbatim_kbinput(win, escape_seq, &es_len,
153 FALSE);
154
155 if (es_len > 1) {
156 /* The escape sequence is more than one character
157 * long. Set meta_key to FALSE, translate the escape
158 * sequence into the corresponding key value, and save
159 * that as the result. */
160 *meta_key = FALSE;
161 if ((retval = get_escape_seq_kbinput(escape_seq,
162 es_len)) == ERR) {
163 /* This escape sequence is unrecognized. Send it
164 * back. */
165 for (; es_len > 1; es_len--)
166 ungetch(escape_seq[es_len - 1]);
167 retval = escape_seq[0];
168 }
169 }
170 free(escape_seq);
171 }
172 }
173
174#ifdef DEBUG
175 fprintf(stderr, "get_kbinput(): kbinput = %d, meta_key = %d\n", kbinput, *meta_key);
176#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000177
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000178#ifndef NANO_SMALL
179 allow_pending_sigwinch(FALSE);
180#endif
181
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000182 return retval;
183}
184
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000185/* Translate acceptable ASCII, extended keypad values, and escape
186 * sequences into their corresponding key values. Set es to TRUE when
187 * we get an escape sequence. Assume nodelay(win) is FALSE. */
188int get_translated_kbinput(int kbinput, int *es
189#ifndef NANO_SMALL
190 , int reset
191#endif
192 )
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000193{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000194 static size_t escapes = 0, ascii_digits = 0;
195 int retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000196
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000197#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000198 if (reset) {
199 escapes = 0;
200 ascii_digits = 0;
201 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000202 }
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000203#endif
204
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000205 *es = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000206
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000207 switch (kbinput) {
208 case ERR:
209 break;
210 case NANO_CONTROL_3:
211 /* Increment the escape counter. */
212 escapes++;
213 switch (escapes) {
214 case 1:
215 /* One escape: wait for more input. */
216 case 2:
217 /* Two escapes: wait for more input. */
218 break;
219 default:
220 /* More than two escapes: reset the escape counter
221 * and wait for more input. */
222 escapes = 0;
223 }
224 break;
225#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
226 /* Since we don't change the default SIGWINCH handler when
227 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
228 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
229 case KEY_RESIZE:
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000230#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000231#ifdef PDCURSES
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000232 case KEY_SHIFT_L:
233 case KEY_SHIFT_R:
234 case KEY_CONTROL_L:
235 case KEY_CONTROL_R:
236 case KEY_ALT_L:
237 case KEY_ALT_R:
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000238#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000239 retval = ERR;
240 break;
241 default:
242 switch (escapes) {
243 case 0:
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000244 switch (kbinput) {
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000245 case NANO_CONTROL_8:
246 retval = ISSET(REBIND_DELETE) ?
247 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000248 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000249 case KEY_DOWN:
250 retval = NANO_NEXTLINE_KEY;
251 break;
252 case KEY_UP:
253 retval = NANO_PREVLINE_KEY;
254 break;
255 case KEY_LEFT:
256 retval = NANO_BACK_KEY;
257 break;
258 case KEY_RIGHT:
259 retval = NANO_FORWARD_KEY;
260 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000261#ifdef KEY_HOME
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000262 /* HP-UX 10 and 11 don't support KEY_HOME. */
263 case KEY_HOME:
264 retval = NANO_HOME_KEY;
265 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000266#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000267 case KEY_BACKSPACE:
268 retval = NANO_BACKSPACE_KEY;
269 break;
270 case KEY_DC:
271 retval = ISSET(REBIND_DELETE) ?
272 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
273 break;
274 case KEY_IC:
275 retval = NANO_INSERTFILE_KEY;
276 break;
277 case KEY_NPAGE:
278 retval = NANO_NEXTPAGE_KEY;
279 break;
280 case KEY_PPAGE:
281 retval = NANO_PREVPAGE_KEY;
282 break;
283 case KEY_ENTER:
284 retval = NANO_ENTER_KEY;
285 break;
286 case KEY_B2: /* Center (5) on numeric keypad
287 * with NumLock off on xterm. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000288#ifdef KEY_BEG
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000289 /* Slang doesn't support KEY_BEG. */
290 case KEY_BEG: /* Center (5) on numeric keypad
291 * with NumLock off on Eterm. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000292#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000293 retval = ERR;
294 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000295#ifdef KEY_END
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000296 /* HP-UX 10 and 11 don't support KEY_END. */
297 case KEY_END:
298 retval = NANO_END_KEY;
299 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000300#endif
301#ifdef KEY_SUSPEND
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000302 /* Slang doesn't support KEY_SUSPEND. */
303 case KEY_SUSPEND:
304 retval = NANO_SUSPEND_KEY;
305 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000306#endif
307#ifdef KEY_SLEFT
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000308 /* Slang doesn't support KEY_SLEFT. */
309 case KEY_SLEFT:
310 retval = NANO_BACK_KEY;
311 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000312#endif
313#ifdef KEY_SRIGHT
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000314 /* Slang doesn't support KEY_SRIGHT. */
315 case KEY_SRIGHT:
316 retval = NANO_FORWARD_KEY;
317 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000318#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000319 default:
320 retval = kbinput;
321 break;
322 }
323 break;
324 case 1:
325 /* One escape followed by a non-escape: escape
326 * sequence mode. Reset the escape counter and set
327 * es to TRUE. */
328 escapes = 0;
329 *es = TRUE;
330 break;
331 case 2:
332 switch (kbinput) {
333 case '0':
334 case '1':
335 case '2':
336 case '3':
337 case '4':
338 case '5':
339 case '6':
340 case '7':
341 case '8':
342 case '9':
343 /* Two escapes followed by one or more
344 * digits: ASCII character sequence mode.
345 * If the digit sequence's range is limited
346 * to 2XX (the first digit is in the '0' to
347 * '2' range and it's the first digit, or if
348 * it's in the full digit range and it's not
349 * the first digit), increment the ASCII
350 * digit counter and interpret the digit.
351 * If the digit sequence's range is not
352 * limited to 2XX, fall through. */
353 if (kbinput <= '2' || ascii_digits > 0) {
354 ascii_digits++;
355 kbinput = get_ascii_kbinput(kbinput,
356 ascii_digits
357#ifndef NANO_SMALL
358 , FALSE
359#endif
360 );
361
362 if (kbinput != ERR) {
363 /* If we've read in a complete ASCII
364 * digit sequence, reset the ASCII
365 * digit counter and the escape
366 * counter and save the corresponding
367 * ASCII character as the result. */
368 ascii_digits = 0;
369 escapes = 0;
370 retval = kbinput;
371 }
372 break;
373 }
374 default:
375 /* Reset the escape counter. */
376 escapes = 0;
377 if (ascii_digits == 0)
378 /* Two escapes followed by a non-digit
379 * or a digit that would create an ASCII
380 * digit sequence greater than 2XX, and
381 * we're not in the middle of an ASCII
382 * character sequence: control character
383 * sequence mode. Interpret the control
384 * sequence and save the corresponding
385 * control character as the result. */
386 retval = get_control_kbinput(kbinput);
387 else {
388 /* If we were in the middle of an ASCII
389 * character sequence, reset the ASCII
390 * digit counter and save the character
391 * we got as the result. */
392 ascii_digits = 0;
393 retval = kbinput;
394 }
395 }
396 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000397 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000398
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000399#ifdef DEBUG
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000400 fprintf(stderr, "get_translated_kbinput(): kbinput = %d, es = %d, escapes = %d, ascii_digits = %d, retval = %d\n", kbinput, *es, escapes, ascii_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000401#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000402
403 /* Return the result. */
404 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000405}
406
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000407/* Translate an ASCII character sequence: turn a three-digit decimal
408 * ASCII code from 000-255 into its corresponding ASCII character. */
409int get_ascii_kbinput(int kbinput, size_t ascii_digits
410#ifndef NANO_SMALL
411 , int reset
412#endif
413 )
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000414{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000415 static int ascii_kbinput = 0;
416 int retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000417
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000418#ifndef NANO_SMALL
419 if (reset) {
420 ascii_kbinput = 0;
421 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000422 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000423#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000424
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000425 switch (ascii_digits) {
426 case 1:
427 /* Read in the first of the three ASCII digits. */
428 switch (kbinput) {
429 /* Add the digit we got to the 100's position of the
430 * ASCII character sequence holder. */
431 case '0':
432 case '1':
433 case '2':
434 ascii_kbinput += (kbinput - '0') * 100;
435 break;
436 default:
437 retval = kbinput;
438 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000439 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000440 case 2:
441 /* Read in the second of the three ASCII digits. */
442 switch (kbinput) {
443 /* Add the digit we got to the 10's position of the
444 * ASCII character sequence holder. */
445 case '0':
446 case '1':
447 case '2':
448 case '3':
449 case '4':
450 case '5':
451 ascii_kbinput += (kbinput - '0') * 10;
452 break;
453 case '6':
454 case '7':
455 case '8':
456 case '9':
457 if (ascii_kbinput < 200) {
458 ascii_kbinput += (kbinput - '0') * 10;
459 break;
460 }
461 default:
462 retval = kbinput;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000463 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000464 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000465 case 3:
466 /* Read in the third of the three ASCII digits. */
467 switch (kbinput) {
468 /* Add the digit we got to the 1's position of the ASCII
469 * character sequence holder, and save the corresponding
470 * ASCII character as the result. */
471 case '0':
472 case '1':
473 case '2':
474 case '3':
475 case '4':
476 case '5':
477 ascii_kbinput += (kbinput - '0');
478 retval = ascii_kbinput;
479 break;
480 case '6':
481 case '7':
482 case '8':
483 case '9':
484 if (ascii_kbinput < 250) {
485 ascii_kbinput += (kbinput - '0');
486 retval = ascii_kbinput;
487 break;
488 }
489 default:
490 retval = kbinput;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000491 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000492 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000493 }
494
495#ifdef DEBUG
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000496 fprintf(stderr, "get_ascii_kbinput(): kbinput = %d, ascii_digits = %d, ascii_kbinput = %d, retval = %d\n", kbinput, ascii_digits, ascii_kbinput, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000497#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000498
499 /* If the result is an ASCII character, reset the ASCII character
500 * sequence holder. */
501 if (retval != ERR)
502 ascii_kbinput = 0;
503
504 return retval;
505}
506
507/* Translate a control character sequence: turn an ASCII non-control
508 * character into its corresponding control character. */
509int get_control_kbinput(int kbinput)
510{
511 int retval = ERR;
512
513 /* We don't handle Ctrl-2 here, since Esc Esc 2 could be the first
514 * part of an ASCII character sequence. */
515
516 /* Ctrl-2 (Ctrl-Space) == Ctrl-@ == Ctrl-` */
517 if (kbinput == ' ' || kbinput == '@' || kbinput == '`')
518 retval = NANO_CONTROL_SPACE;
519 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
520 else if (kbinput >= '3' && kbinput <= '7')
521 retval = kbinput - 24;
522 /* Ctrl-8 (Ctrl-?) */
523 else if (kbinput == '8' || kbinput == '?')
524 retval = NANO_CONTROL_8;
525 /* Ctrl-A to Ctrl-_ */
526 else if (kbinput >= 'A' && kbinput <= '_')
527 retval = kbinput - 64;
528 /* Ctrl-a to Ctrl-~ */
529 else if (kbinput >= 'a' && kbinput <= '~')
530 retval = kbinput - 96;
531 else
532 retval = kbinput;
533
534#ifdef DEBUG
535 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, ascii_digits, *complete, retval);
536#endif
537
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000538 return retval;
539}
540
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000541/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000542 * keypad values, nto their corresponding key values. These sequences
543 * are generated when the keypad doesn't support the needed keys.
544 * Assume that Escape has already been read in. */
545int get_escape_seq_kbinput(int *escape_seq, size_t es_len)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000546{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000547 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000548
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000549 if (es_len > 1) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000550 switch (escape_seq[0]) {
551 case 'O':
552 switch (escape_seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000553 case '2':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000554 if (es_len >= 3) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000555 switch (escape_seq[2]) {
556 case 'P': /* Esc O 2 P == F13 on
557 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000558 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000559 break;
560 case 'Q': /* Esc O 2 Q == F14 on
561 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000562 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000563 break;
564 }
565 }
566 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000567 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
568 case 'B': /* Esc O B == Down on
569 * VT100/VT320/xterm. */
570 case 'C': /* Esc O C == Right on
571 * VT100/VT320/xterm. */
572 case 'D': /* Esc O D == Left on
573 * VT100/VT320/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000574 retval = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000575 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000576 case 'E': /* Esc O E == Center (5) on numeric keypad
577 * with NumLock off on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000578 retval = ERR;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000579 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000580 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000581 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000582 break;
583 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000584 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000585 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000586 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000587 * NumLock off on
588 * VT100/VT220/VT320/xterm/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000589 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000590 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000591 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Hurd
592 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000593 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000594 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000595 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Hurd
596 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000597 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000598 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000599 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Hurd
600 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000601 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000602 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000603 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Hurd
604 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000605 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000606 break;
607 case 'T': /* Esc O T == F5 on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000608 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000609 break;
610 case 'U': /* Esc O U == F6 on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000611 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000612 break;
613 case 'V': /* Esc O V == F7 on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000614 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000615 break;
616 case 'W': /* Esc O W == F8 on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000617 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000618 break;
619 case 'X': /* Esc O X == F9 on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000620 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000621 break;
622 case 'Y': /* Esc O Y == F10 on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000623 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000624 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000625 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000626 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000627 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000628 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000629 retval = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000630 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000631 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000632 * NumLock off on
633 * VT100/VT220/VT320/xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000634 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000635 break;
636 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000637 * NumLock off on
638 * VT100/VT220/VT320/xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000639 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000640 break;
641 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000642 * NumLock off on
643 * VT100/VT220/VT320/xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000644 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000645 break;
646 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000647 * NumLock off on
648 * VT100/VT220/VT320/xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000649 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000650 break;
651 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000652 * with NumLock off on
653 * VT100/VT220/VT320/xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000654 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000655 break;
656 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000657 * NumLock off on
658 * VT100/VT220/VT320/xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000659 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000660 break;
661 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000662 * with NumLock off on
663 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000664 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000665 break;
666 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000667 * with NumLock off on
668 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000669 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000670 break;
671 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000672 * with NumLock off on
673 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000674 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000675 break;
676 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000677 * keypad with NumLock off on
678 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000679 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000680 break;
681 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000682 * with NumLock off on
683 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000684 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000685 break;
686 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000687 * with NumLock off on
688 * VT100/VT220/VT320/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000689 retval = ERR;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000690 break;
691 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000692 * with NumLock off on
693 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000694 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000695 break;
696 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000697 * with NumLock off on
698 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000699 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000700 break;
701 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000702 * with NumLock off on
703 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000704 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000705 break;
706 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000707 * with NumLock off on
708 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000709 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000710 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000711 }
712 break;
713 case 'o':
714 switch (escape_seq[1]) {
715 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000716 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000717 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000718 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000719 retval = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000720 break;
721 }
722 break;
723 case '[':
724 switch (escape_seq[1]) {
725 case '1':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000726 if (es_len >= 3) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000727 switch (escape_seq[2]) {
728 case '1': /* Esc [ 1 1 ~ == F1 on
729 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000730 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000731 break;
732 case '2': /* Esc [ 1 2 ~ == F2 on
733 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000734 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000735 break;
736 case '3': /* Esc [ 1 3 ~ == F3 on
737 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000738 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000739 break;
740 case '4': /* Esc [ 1 4 ~ == F4 on
741 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000742 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000743 break;
744 case '5': /* Esc [ 1 5 ~ == F5 on
745 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000746 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000747 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000748 case '7': /* Esc [ 1 7 ~ == F6 on
749 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000750 * console/xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000751 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000752 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000753 case '8': /* Esc [ 1 8 ~ == F7 on
754 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000755 * console/xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000756 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000757 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000758 case '9': /* Esc [ 1 9 ~ == F8 on
759 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000760 * console/xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000761 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000762 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000763 case ';':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000764 if (es_len >= 4) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000765 switch (escape_seq[3]) {
766 case '2':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000767 if (es_len >= 5) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000768 switch (escape_seq[4]) {
769 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
770 * xterm. */
771 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
772 * xterm. */
773 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
774 * xterm. */
775 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
776 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000777 retval = get_escape_seq_abcd(escape_seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000778 break;
779 }
780 }
781 break;
782 case '5':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000783 if (es_len >= 5) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000784 switch (escape_seq[4]) {
785 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
786 * xterm. */
787 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
788 * xterm. */
789 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
790 * xterm. */
791 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
792 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000793 retval = get_escape_seq_abcd(escape_seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000794 break;
795 }
796 }
797 break;
798 }
799 }
800 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000801 default: /* Esc [ 1 ~ == Home on
802 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000803 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000804 break;
805 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000806 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000807 break;
808 case '2':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000809 if (es_len >= 3) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000810 switch (escape_seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000811 case '0': /* Esc [ 2 0 ~ == F9 on
812 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000813 * console/xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000814 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000815 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000816 case '1': /* Esc [ 2 1 ~ == F10 on
817 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000818 * console/xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000819 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000820 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000821 case '3': /* Esc [ 2 3 ~ == F11 on
822 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000823 * console/xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000824 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000825 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000826 case '4': /* Esc [ 2 4 ~ == F12 on
827 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000828 * console/xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000829 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000830 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000831 case '5': /* Esc [ 2 5 ~ == F13 on
832 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000833 * console/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000834 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000835 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000836 case '6': /* Esc [ 2 6 ~ == F14 on
837 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000838 * console/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000839 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000840 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000841 default: /* Esc [ 2 ~ == Insert on
842 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000843 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000844 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000845 break;
846 }
847 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000848 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000849 case '3': /* Esc [ 3 ~ == Delete on
850 * VT220/VT320/Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000851 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000852 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000853 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000854 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000855 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000856 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000857 case '5': /* Esc [ 5 ~ == PageUp on
858 * VT220/VT320/Linux console/xterm; Esc [
859 * 5 ^ == PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000860 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000861 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000862 case '6': /* Esc [ 6 ~ == PageDown on
863 * VT220/VT320/Linux console/xterm; Esc [
864 * 6 ^ == PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000865 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000866 break;
867 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000868 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000869 break;
870 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000871 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000872 break;
873 case '9': /* Esc [ 9 == Delete on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000874 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000875 break;
876 case '@': /* Esc [ @ == Insert on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000877 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000878 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000879 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000880 * console/FreeBSD console/Hurd
881 * console/rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000882 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000883 * console/FreeBSD console/Hurd
884 * console/rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000885 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
886 * console/FreeBSD console/Hurd
887 * console/rxvt/Eterm. */
888 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000889 * console/FreeBSD console/Hurd
890 * console/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000891 retval = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000892 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000893 case 'E': /* Esc [ E == Center (5) on numeric keypad
894 * with NumLock off on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000895 retval = ERR;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000896 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000897 case 'F': /* Esc [ F == End on FreeBSD
898 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000899 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000900 break;
901 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000902 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000903 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000904 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000905 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000906 * console/Hurd console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000907 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000908 break;
909 case 'I': /* Esc [ I == PageUp on FreeBSD
910 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000911 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000912 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000913 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000914 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000915 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000916 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000917 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000918 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000919 break;
920 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000921 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000922 break;
923 case 'O':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000924 if (es_len >= 3) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000925 switch (escape_seq[2]) {
926 case 'P': /* Esc [ O P == F1 on
927 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000928 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000929 break;
930 case 'Q': /* Esc [ O Q == F2 on
931 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000932 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000933 break;
934 case 'R': /* Esc [ O R == F3 on
935 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000936 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000937 break;
938 case 'S': /* Esc [ O S == F4 on
939 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000940 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000941 break;
942 default: /* Esc [ O == F3 on
943 * FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000944 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000945 break;
946 }
947 }
948 break;
949 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000950 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000951 break;
952 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000953 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000954 break;
955 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000956 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000957 break;
958 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000959 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000960 break;
961 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000962 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000963 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000964 case 'U': /* Esc [ U == PageDown on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000965 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000966 break;
967 case 'V': /* Esc [ V == PageUp on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000968 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000969 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000970 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000971 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000972 break;
973 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000974 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000975 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000976 case 'Y': /* Esc [ Y == End on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000977 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000978 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000979 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000980 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000981 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +0000982 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +0000983 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +0000984 case 'c': /* Esc [ c == Shift-Right on
985 * rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +0000986 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000987 retval = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000988 break;
989 case '[':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000990 if (es_len >= 3) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000991 switch (escape_seq[2]) {
992 case 'A': /* Esc [ [ A == F1 on Linux
993 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000994 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000995 break;
996 case 'B': /* Esc [ [ B == F2 on Linux
997 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000998 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000999 break;
1000 case 'C': /* Esc [ [ C == F3 on Linux
1001 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001002 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001003 break;
1004 case 'D': /* Esc [ [ D == F4 on Linux
1005 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001006 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001007 break;
1008 case 'E': /* Esc [ [ E == F5 on Linux
1009 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001010 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001011 break;
1012 }
1013 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001014 break;
1015 }
1016 break;
1017 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001018 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001019
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001020#ifdef DEBUG
1021 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d\n", retval);
1022#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001023
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001024 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001025}
1026
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001027/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001028 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001029 * to many escape sequences. */
1030int get_escape_seq_abcd(int kbinput)
1031{
1032 switch (tolower(kbinput)) {
1033 case 'a':
1034 return NANO_PREVLINE_KEY;
1035 case 'b':
1036 return NANO_NEXTLINE_KEY;
1037 case 'c':
1038 return NANO_FORWARD_KEY;
1039 case 'd':
1040 return NANO_BACK_KEY;
1041 default:
1042 return ERR;
1043 }
1044}
1045
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001046/* Read in a string of input characters (e.g. an escape sequence)
1047 * verbatim. Store the string in v_kbinput and return the length
1048 * of the string in v_len. Assume nodelay(win) is FALSE. */
1049int *get_verbatim_kbinput(WINDOW *win, int *v_kbinput, size_t
1050 *v_len, int allow_ascii)
1051{
1052 int kbinput;
1053 size_t i = 0, v_newlen = 0;
1054
1055#ifndef NANO_SMALL
1056 allow_pending_sigwinch(TRUE);
1057#endif
1058
1059 *v_len = 0;
1060 v_kbinput = (int *)nmalloc(sizeof(int));
1061
1062 /* Turn off flow control characters if necessary so that we can type
1063 * them in verbatim, and turn the keypad off so that we don't get
1064 * extended keypad values outside the ASCII range. */
1065 if (ISSET(PRESERVE))
1066 disable_flow_control();
1067 keypad(win, FALSE);
1068
1069 /* Read the first character using blocking input, since using
1070 * non-blocking input will eat up all unused CPU. Then increment
1071 * v_len and save the character in v_kbinput. */
1072 kbinput = wgetch(win);
1073 (*v_len)++;
1074 v_kbinput[0] = kbinput;
1075#ifdef DEBUG
1076 fprintf(stderr, "get_verbatim_kbinput(): kbinput = %d, v_len = %d\n", kbinput, *v_len);
1077#endif
1078
1079 /* Read any following characters using non-blocking input, until
1080 * there aren't any left to be read, and save the complete string of
1081 * characters in v_kbinput, incrementing v_len accordingly. We read
1082 * them all at once in order to minimize the chance that there might
1083 * be a delay greater than nodelay() provides for between them, in
1084 * which case we'll stop before all of them are read. */
1085 nodelay(win, TRUE);
1086 while ((kbinput = wgetch(win)) != ERR) {
1087 (*v_len)++;
1088 v_kbinput = (int *)nrealloc(v_kbinput, *v_len * sizeof(int));
1089 v_kbinput[*v_len - 1] = kbinput;
1090#ifdef DEBUG
1091 fprintf(stderr, "get_verbatim_kbinput(): kbinput = %d, v_len = %d\n", kbinput, *v_len);
1092#endif
1093 }
1094 nodelay(win, FALSE);
1095
1096 /* Pass the string of characters to get_untranslated_kbinput(), one
1097 * by one, so it can handle them as ASCII character sequences and/or
1098 * escape sequences. Filter out ERR's from v_kbinput in the
1099 * process; they shouldn't occur in the string of characters unless
1100 * we're reading an incomplete sequence, in which case we only want
1101 * to keep the complete sequence. */
1102 for (; i < *v_len; i++) {
1103 v_kbinput[v_newlen] = get_untranslated_kbinput(v_kbinput[i], i,
1104 allow_ascii
1105#ifndef NANO_SMALL
1106 , FALSE
1107#endif
1108 );
1109 if (v_kbinput[i] != ERR && v_kbinput[v_newlen] != ERR)
1110 v_newlen++;
1111 }
1112
1113 if (v_newlen == 0) {
1114 /* If there were no characters after the ERR's were filtered
1115 * out, set v_len and reallocate v_kbinput to account for
1116 * one character, and set that character to ERR. */
1117 *v_len = 1;
1118 v_kbinput = (int *)nrealloc(v_kbinput, sizeof(int));
1119 v_kbinput[0] = ERR;
1120 } else if (v_newlen != *v_len) {
1121 /* If there were fewer characters after the ERR's were filtered
1122 * out, set v_len and reallocate v_kbinput to account for
1123 * the new number of characters. */
1124 *v_len = v_newlen;
1125 v_kbinput = (int *)nrealloc(v_kbinput, *v_len * sizeof(int));
1126 }
1127
1128 /* If allow_ascii is TRUE and v_kbinput[0] is ERR, we need to
1129 * complete an ASCII character sequence. Keep reading in characters
1130 * using blocking input until we get a complete sequence. */
1131 if (allow_ascii && v_kbinput[0] == ERR) {
1132 while (v_kbinput[0] == ERR) {
1133 kbinput = wgetch(win);
1134 v_kbinput[0] = get_untranslated_kbinput(kbinput, i,
1135 allow_ascii
1136#ifndef NANO_SMALL
1137 , FALSE
1138#endif
1139 );
1140 i++;
1141 }
1142 }
1143
1144 /* Turn flow control characters back on if necessary and turn the
1145 * keypad back on now that we're done. */
1146 if (ISSET(PRESERVE))
1147 enable_flow_control();
1148 keypad(win, TRUE);
1149
1150#ifndef NANO_SMALL
1151 allow_pending_sigwinch(FALSE);
1152#endif
1153
1154 return v_kbinput;
1155}
1156
1157int get_untranslated_kbinput(int kbinput, size_t position, int
1158 allow_ascii
1159#ifndef NANO_SMALL
1160 , int reset
1161#endif
1162 )
1163{
1164 static size_t ascii_digits = 0;
1165 int retval;
1166
1167#ifndef NANO_SMALL
1168 if (reset) {
1169 ascii_digits = 0;
1170 return ERR;
1171 }
1172#endif
1173
1174 if (allow_ascii) {
1175 /* position is equal to the number of ASCII digits we've read so
1176 * far, and kbinput is a digit from '0' to '9': ASCII character
1177 * sequence mode. If the digit sequence's range is limited to
1178 * 2XX (the first digit is in the '0' to '2' range and it's the
1179 * first digit, or if it's in the full digit range and it's not
1180 * the first digit), increment the ASCII digit counter and
1181 * interpret the digit. If the digit sequence's range is not
1182 * limited to 2XX, fall through. */
1183 if (position == ascii_digits && kbinput >= '0' && kbinput <= '9') {
1184 if (kbinput <= '2' || ascii_digits > 0) {
1185 ascii_digits++;
1186 kbinput = get_ascii_kbinput(kbinput, ascii_digits
1187#ifndef NANO_SMALL
1188 , FALSE
1189#endif
1190 );
1191 if (kbinput != ERR)
1192 /* If we've read in a complete ASCII digit sequence,
1193 * reset the ASCII digit counter. */
1194 ascii_digits = 0;
1195 }
1196 } else if (ascii_digits > 0)
1197 /* position is not equal to the number of ASCII digits we've
1198 * read or kbinput is a non-digit, and we're in the middle
1199 * of an ASCII character sequence. Reset the ASCII digit
1200 * counter. */
1201 ascii_digits = 0;
1202 }
1203
1204 /* Save the corresponding ASCII character as the result if we've
1205 * read in a complete ASCII digit sequence, or the passed-in
1206 * character if we haven't. */
1207 retval = kbinput;
1208
1209#ifdef DEBUG
1210 fprintf(stderr, "get_untranslated_kbinput(): kbinput = %d, position = %d, ascii_digits = %d\n", kbinput, position, ascii_digits);
1211#endif
1212
1213 return retval;
1214}
1215
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001216#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001217/* Check for a mouse event, and if one's taken place, save the
1218 * coordinates where it took place in mouse_x and mouse_y. After that,
1219 * if allow_shortcuts is zero, return 0. Otherwise, if the mouse event
1220 * took place on the shortcut list on the bottom two lines of the screen
1221 * (assuming that the shortcut list is visible), figure out which
1222 * shortcut was clicked and ungetch() the equivalent keystroke(s).
1223 * Return 0 if no keystrokes were ungetch()ed, or 1 if at least one was.
1224 * Assume that KEY_MOUSE has already been read in. */
1225int get_mouseinput(int *mouse_x, int *mouse_y, int allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001226{
1227 MEVENT mevent;
1228
1229 *mouse_x = -1;
1230 *mouse_y = -1;
1231
1232 /* First, get the actual mouse event. */
1233 if (getmouse(&mevent) == ERR)
1234 return 0;
1235
1236 /* Save the screen coordinates where the mouse event took place. */
1237 *mouse_x = mevent.x;
1238 *mouse_y = mevent.y;
1239
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001240 /* If we're not allowing shortcuts' we're done now. */
1241 if (!allow_shortcuts)
1242 return 0;
1243
1244 /* Otherwise, if the current shortcut list is being displayed on the
1245 * last two lines of the screen and the mouse event took place
1246 * inside it, we need to figure out which shortcut was clicked and
1247 * ungetch() the equivalent keystroke(s) for it. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001248 if (!ISSET(NO_HELP) && wenclose(bottomwin, *mouse_y, *mouse_x)) {
1249 int i, j;
1250 int currslen;
1251 /* The number of shortcuts in the current shortcut list. */
1252 const shortcut *s = currshortcut;
1253 /* The actual shortcut we clicked on, starting at the first
1254 * one in the current shortcut list. */
1255
1256 /* Get the shortcut lists' length. */
1257 if (currshortcut == main_list)
1258 currslen = MAIN_VISIBLE;
1259 else
1260 currslen = length_of_list(currshortcut);
1261
1262 /* Calculate the width of each shortcut in the list (it's the
1263 * same for all of them). */
1264 if (currslen < 2)
1265 i = COLS / 6;
1266 else
1267 i = COLS / ((currslen / 2) + (currslen % 2));
1268
1269 /* Calculate the y-coordinates relative to the beginning of
1270 * bottomwin, i.e, the bottom three lines of the screen. */
1271 j = *mouse_y - (editwinrows + 3);
1272
1273 /* If we're on the statusbar, beyond the end of the shortcut
1274 * list, or beyond the end of a shortcut on the right side of
1275 * the screen, don't do anything. */
1276 if (j < 0 || (*mouse_x / i) >= currslen)
1277 return 0;
1278 j = (*mouse_x / i) * 2 + j;
1279 if (j >= currslen)
1280 return 0;
1281
1282 /* Go through the shortcut list to determine which shortcut was
1283 * clicked. */
1284 for (; j > 0; j--)
1285 s = s->next;
1286
David Lawrence Ramsey32613fa2004-05-24 18:40:41 +00001287 /* And ungetch() the equivalent control key. If it's a meta key
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001288 * sequence, we need to ungetch() Escape too. Assume that the
1289 * shortcut has an equivalent control key, meta key sequence, or
1290 * both. */
1291 if (s->ctrlval != NANO_NO_KEY)
1292 ungetch(s->ctrlval);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001293 else if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001294 ungetch(s->metaval);
1295 ungetch(NANO_CONTROL_3);
1296 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001297
1298 return 1;
1299 }
1300 return 0;
1301}
1302#endif
1303
Chris Allegretta6df90f52002-07-19 01:08:59 +00001304/* Return the placewewant associated with current_x. That is, xplustabs
1305 * is the zero-based column position of the cursor. Value is no smaller
1306 * than current_x. */
1307size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001308{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001309 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001310}
1311
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001312/* actual_x() gives the index in str of the character displayed at
1313 * column xplus. That is, actual_x() is the largest value such that
1314 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
1315size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001316{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001317 size_t i = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001318 /* the position in str, returned */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001319 size_t length = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001320 /* the screen display width to str[i] */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001321
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001322 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001323
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001324 for (; length < xplus && *str != '\0'; i++, str++) {
1325 if (*str == '\t')
David Lawrence Ramsey0362c582003-09-30 03:31:56 +00001326 length += tabsize - (length % tabsize);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001327 else if (is_cntrl_char((int)*str))
Chris Allegretta6df90f52002-07-19 01:08:59 +00001328 length += 2;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001329 else
1330 length++;
1331 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001332 assert(length == strnlenpt(str - i, i));
1333 assert(i <= strlen(str - i));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001334
Chris Allegretta6df90f52002-07-19 01:08:59 +00001335 if (length > xplus)
1336 i--;
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001337
Chris Allegretta6df90f52002-07-19 01:08:59 +00001338 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00001339}
1340
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00001341/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001342 * columns wide are the first size characters of buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001343size_t strnlenpt(const char *buf, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00001344{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001345 size_t length = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001346
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001347 assert(buf != NULL);
1348 for (; *buf != '\0' && size != 0; size--, buf++) {
1349 if (*buf == '\t')
1350 length += tabsize - (length % tabsize);
1351 else if (is_cntrl_char((int)*buf))
1352 length += 2;
1353 else
1354 length++;
1355 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001356 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001357}
1358
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001359/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001360size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001361{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00001362 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001363}
1364
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001365void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001366{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001367 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001368}
1369
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001370void blank_edit(void)
1371{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001372 size_t i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001373 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001374 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001375}
1376
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001377void blank_statusbar(void)
1378{
1379 mvwaddstr(bottomwin, 0, 0, hblank);
1380}
1381
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001382void check_statblank(void)
1383{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001384 if (statblank > 1)
1385 statblank--;
1386 else if (statblank == 1 && !ISSET(CONSTUPDATE)) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001387 statblank = 0;
1388 blank_statusbar();
1389 wnoutrefresh(bottomwin);
1390 reset_cursor();
1391 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001392 }
1393}
1394
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001395void blank_bottombars(void)
1396{
1397 if (!ISSET(NO_HELP)) {
1398 mvwaddstr(bottomwin, 1, 0, hblank);
1399 mvwaddstr(bottomwin, 2, 0, hblank);
1400 }
1401}
1402
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001403/* Convert buf into a string that can be displayed on screen. The
1404 * caller wants to display buf starting with column start_col, and
1405 * extending for at most len columns. start_col is zero-based. len is
1406 * one-based, so len == 0 means you get "" returned. The returned
1407 * string is dynamically allocated, and should be freed. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001408char *display_string(const char *buf, size_t start_col, size_t len)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001409{
1410 size_t start_index;
1411 /* Index in buf of first character shown in return value. */
1412 size_t column;
1413 /* Screen column start_index corresponds to. */
1414 size_t end_index;
1415 /* Index in buf of last character shown in return value. */
1416 size_t alloc_len;
1417 /* The length of memory allocated for converted. */
1418 char *converted;
1419 /* The string we return. */
1420 size_t index;
1421 /* Current position in converted. */
1422
1423 if (len == 0)
1424 return mallocstrcpy(NULL, "");
1425
1426 start_index = actual_x(buf, start_col);
1427 column = strnlenpt(buf, start_index);
1428 assert(column <= start_col);
1429 end_index = actual_x(buf, start_col + len - 1);
1430 alloc_len = strnlenpt(buf, end_index + 1) - column;
1431 if (len > alloc_len + column - start_col)
1432 len = alloc_len + column - start_col;
1433 converted = charalloc(alloc_len + 1);
1434 buf += start_index;
1435 index = 0;
1436
1437 for (; index < alloc_len; buf++) {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001438 if (*buf == '\t') {
1439 converted[index++] =
1440#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
1441 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
1442#endif
1443 ' ';
1444 while ((column + index) % tabsize)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001445 converted[index++] = ' ';
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001446 } else if (is_cntrl_char(*buf)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001447 converted[index++] = '^';
1448 if (*buf == '\n')
1449 /* Treat newlines embedded in a line as encoded nulls;
1450 * the line in question should be run through unsunder()
1451 * before reaching here. */
1452 converted[index++] = '@';
1453 else if (*buf == NANO_CONTROL_8)
1454 converted[index++] = '?';
1455 else
1456 converted[index++] = *buf + 64;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001457 } else if (*buf == ' ')
1458 converted[index++] =
1459#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
1460 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
1461#endif
1462 ' ';
1463 else
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001464 converted[index++] = *buf;
1465 }
1466 assert(len <= alloc_len + column - start_col);
1467 charmove(converted, converted + start_col - column, len);
1468 null_at(&converted, len);
1469
1470 return charealloc(converted, len + 1);
1471}
1472
Chris Allegretta7662c862003-01-13 01:35:15 +00001473/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001474 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00001475 *
Chris Allegretta7662c862003-01-13 01:35:15 +00001476 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00001477 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001478void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001479{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001480 size_t x_real = strnlenpt(inputbuf, x);
1481 int wid = COLS - strlen(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00001482
Chris Allegretta6df90f52002-07-19 01:08:59 +00001483 assert(0 <= x && x <= strlen(inputbuf));
1484
Chris Allegrettab3655b42001-10-22 03:15:31 +00001485 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001486 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001487
Chris Allegretta6df90f52002-07-19 01:08:59 +00001488 mvwaddstr(bottomwin, 0, 0, buf);
1489 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001490
1491 if (COLS > 1)
1492 waddch(bottomwin, x_real < wid ? ' ' : '$');
1493 if (COLS > 2) {
1494 size_t page_start = x_real - x_real % wid;
1495 char *expanded = display_string(inputbuf, page_start, wid);
1496
1497 assert(wid > 0);
1498 assert(strlen(expanded) <= wid);
1499 waddstr(bottomwin, expanded);
1500 free(expanded);
1501 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
1502 } else
1503 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001504 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001505}
1506
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00001507/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00001508 * statusq(). */
Chris Allegrettaf717f982003-02-13 22:25:01 +00001509int nanogetstr(int allowtabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00001510#ifndef NANO_SMALL
1511 historyheadtype *history_list,
1512#endif
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001513 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00001514#ifndef DISABLE_TABCOMP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001515 , int *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00001516#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00001517 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00001518{
1519 int kbinput;
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001520 int meta_key;
Chris Allegretta09fc4302003-01-16 22:16:38 +00001521 static int x = -1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001522 /* the cursor position in 'answer' */
1523 int xend;
1524 /* length of 'answer', the status bar text */
1525 int tabbed = 0;
1526 /* used by input_tab() */
1527 const shortcut *t;
Chris Allegretta598106e2002-01-19 01:59:37 +00001528
Chris Allegretta5beed502003-01-05 20:41:21 +00001529#ifndef NANO_SMALL
1530 /* for history */
1531 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00001532 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00001533 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001534 int last_kbinput = 0;
1535
1536 /* This variable is used in the search history code. use_cb == 0
1537 means that we're using the existing history and ignoring
1538 currentbuf. use_cb == 1 means that the entry in answer should be
1539 moved to currentbuf or restored from currentbuf to answer.
1540 use_cb == 2 means that the entry in currentbuf should be moved to
1541 answer or restored from answer to currentbuf. */
1542 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00001543#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001544 xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00001545
1546 /* Only put x at the end of the string if it's uninitialized or if
1547 it would be past the end of the string as it is. Otherwise,
1548 leave it alone. This is so the cursor position stays at the same
1549 place if a prompt-changing toggle is pressed. */
Chris Allegretta65f075d2003-02-13 03:03:49 +00001550 if (x == -1 || x > xend || resetstatuspos)
Chris Allegretta09fc4302003-01-16 22:16:38 +00001551 x = xend;
1552
Chris Allegrettae1e0fd62003-04-15 01:15:09 +00001553 answer = charealloc(answer, xend + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001554 if (xend > 0)
1555 strcpy(answer, def);
1556 else
1557 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001558
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00001559#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001560 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00001561#endif
1562
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001563 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00001564
Chris Allegretta6df90f52002-07-19 01:08:59 +00001565 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001566
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001567 /* Make sure any editor screen updates are displayed before getting
1568 input */
Chris Allegretta022b96f2000-11-14 17:47:58 +00001569 wrefresh(edit);
1570
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001571 /* If we're using restricted mode, we aren't allowed to change the
1572 * name of a file once it has one because that would allow writing
1573 * to files not specified on the command line. In this case,
1574 * disable all keys that would change the text if the filename isn't
1575 * blank and we're at the "Write File" prompt. */
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001576 while ((kbinput = get_kbinput(bottomwin, &meta_key)) != NANO_ENTER_KEY) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001577 for (t = s; t != NULL; t = t->next) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001578#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001579 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001580#endif
1581
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001582 /* Temporary hack to interpret NANO_HELP_FKEY correctly. */
1583 if (kbinput == t->funcval)
1584 kbinput = t->ctrlval;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00001585
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001586 if (kbinput == t->ctrlval && is_cntrl_char(kbinput)) {
Chris Allegretta5bf51d32000-11-16 06:01:10 +00001587
Chris Allegrettab3655b42001-10-22 03:15:31 +00001588#ifndef DISABLE_HELP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001589 /* Have to do this here, it would be too late to do it
1590 in statusq() */
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00001591 if (kbinput == NANO_HELP_KEY) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00001592 do_help();
1593 break;
1594 }
1595#endif
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001596#ifndef NANO_SMALL
1597 /* Have to handle these here too, for the time being */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001598 if (kbinput == NANO_PREVLINE_KEY || kbinput == NANO_NEXTLINE_KEY)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001599 break;
1600#endif
Chris Allegretta5af58892003-01-17 21:07:38 +00001601
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001602 return t->ctrlval;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001603 }
1604 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001605 assert(0 <= x && x <= xend && xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001606
Chris Allegretta04d848e2000-11-05 17:54:41 +00001607 if (kbinput != '\t')
1608 tabbed = 0;
1609
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001610 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00001611#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001612 case KEY_MOUSE:
1613 do_mouse();
1614 break;
1615#endif
Chris Allegretta658399a2001-06-14 02:54:22 +00001616 case NANO_HOME_KEY:
David Lawrence Ramseyc7acf692004-05-22 20:15:20 +00001617#ifndef NANO_SMALL
1618 if (ISSET(SMART_HOME)) {
1619 int old_x = x;
1620
1621 for (x = 0; isblank(answer[x]) && x < xend; x++)
1622 ;
1623
1624 if (x == old_x || x == xend)
1625 x = 0;
1626 } else
1627#endif
1628 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001629 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00001630 case NANO_END_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001631 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001632 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00001633 case NANO_FORWARD_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001634 if (x < xend)
1635 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001636 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001637 case NANO_DELETE_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001638 /* If we're using restricted mode, the filename isn't blank,
1639 * and we're at the "Write File" prompt, disable Delete. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001640 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1641 if (x < xend) {
1642 charmove(answer + x, answer + x + 1, xend - x);
1643 xend--;
1644 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001645 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001646 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001647 case NANO_CUT_KEY:
1648 case NANO_UNCUT_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001649 /* If we're using restricted mode, the filename isn't blank,
1650 * and we're at the "Write File" prompt, disable Cut and
1651 * UnCut. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001652 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1653 null_at(&answer, 0);
1654 xend = 0;
1655 x = 0;
1656 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001657 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001658 case NANO_BACKSPACE_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001659 /* If we're using restricted mode, the filename isn't blank,
1660 * and we're at the "Write File" prompt, disable
1661 * Backspace. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001662 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1663 if (x > 0) {
1664 charmove(answer + x - 1, answer + x, xend - x + 1);
1665 x--;
1666 xend--;
1667 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001668 }
Chris Allegretta04d848e2000-11-05 17:54:41 +00001669 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001670 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001671#ifndef NANO_SMALL
1672 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00001673 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001674 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001675 history_list->current = (historytype *)history_list;
1676 history_list->len = strlen(answer);
1677 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001678
Chris Allegretta7662c862003-01-13 01:35:15 +00001679 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001680 complete = get_history_completion(history_list, answer);
1681 xend = strlen(complete);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001682 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00001683 answer = mallocstrcpy(answer, complete);
1684 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00001685 }
Chris Allegretta5beed502003-01-05 20:41:21 +00001686#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00001687 else
1688#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00001689#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00001690#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00001691 if (allowtabs) {
1692 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00001693
Chris Allegretta327abda2003-01-17 05:04:17 +00001694 answer = input_tab(answer, x, &tabbed, &shift, list);
1695 xend = strlen(answer);
1696 x += shift;
1697 if (x > xend)
1698 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00001699 }
1700#endif
1701 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00001702 case NANO_BACK_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001703 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001704 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001705 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001706 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001707#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00001708 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00001709
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001710 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
1711 isn't NULL, and currentbuf is different from answer,
1712 it means that we're scrolling up at the top of the
1713 search history, and we need to save the current
1714 answer in currentbuf; do this and reset use_cb to
1715 0 */
1716 if (currentbuf == NULL || (use_cb == 1 && strcmp(currentbuf, answer))) {
Chris Allegretta8031f832003-01-09 05:29:58 +00001717 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001718 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00001719 }
1720
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001721 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
1722 is different from answer, it means that we're
1723 scrolling up at the bottom of the search history, and
1724 we need to make the string in currentbuf the current
1725 answer; do this, blow away currentbuf since we don't
1726 need it anymore, and reset use_cb to 0 */
1727 if (currentbuf != NULL && use_cb == 2 && strcmp(currentbuf, answer)) {
1728 answer = mallocstrcpy(answer, currentbuf);
1729 free(currentbuf);
1730 currentbuf = NULL;
1731 xend = strlen(answer);
1732 use_cb = 0;
1733
1734 /* else get older search from the history list and save
1735 it in answer; if there is no older search, blank out
1736 answer */
1737 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001738 answer = mallocstrcpy(answer, history);
1739 xend = strlen(history);
1740 } else {
1741 answer = mallocstrcpy(answer, "");
1742 xend = 0;
1743 }
1744 x = xend;
1745 }
Chris Allegretta5beed502003-01-05 20:41:21 +00001746#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00001747 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001748 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001749#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00001750 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001751
1752 /* get newer search from the history list and save it
1753 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00001754 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001755 answer = mallocstrcpy(answer, history);
1756 xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00001757
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001758 /* if there is no newer search, we're here */
1759
1760 /* if currentbuf isn't NULL and use_cb isn't 2, it means
1761 that we're scrolling down at the bottom of the search
1762 history and we need to make the string in currentbuf
1763 the current answer; do this, blow away currentbuf
1764 since we don't need it anymore, and set use_cb to
1765 1 */
1766 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00001767 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00001768 free(currentbuf);
1769 currentbuf = NULL;
1770 xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001771 use_cb = 1;
1772
1773 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
1774 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00001775 the search history and the current answer (if it's
1776 not blank) needs to be saved in currentbuf; do this,
1777 blank out answer (if necessary), and set use_cb to
1778 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001779 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00001780 if (answer[0] != '\0') {
1781 currentbuf = mallocstrcpy(currentbuf, answer);
1782 answer = mallocstrcpy(answer, "");
1783 }
Chris Allegretta5beed502003-01-05 20:41:21 +00001784 xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001785 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00001786 }
1787 x = xend;
1788 }
1789#endif
1790 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00001791 default:
1792
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001793 for (t = s; t != NULL; t = t->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +00001794#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001795 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
Chris Allegretta598106e2002-01-19 01:59:37 +00001796 kbinput);
Chris Allegretta658399a2001-06-14 02:54:22 +00001797#endif
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001798 if (meta_key == TRUE && (kbinput == t->metaval || kbinput == t->miscval))
David Lawrence Ramsey32613fa2004-05-24 18:40:41 +00001799 /* We hit a meta key. Do like above. We don't
David Lawrence Ramsey82138502003-12-24 08:03:54 +00001800 * just ungetch() the letter and let it get
1801 * caught above cause that screws the
1802 * keypad... */
1803 return kbinput;
Chris Allegretta658399a2001-06-14 02:54:22 +00001804 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001805
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001806 /* If we're using restricted mode, the filename isn't blank,
1807 * and we're at the "Write File" prompt, act as though the
1808 * unhandled character we got is a control character and
1809 * throw it away. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001810 if (is_cntrl_char(kbinput) || (ISSET(RESTRICTED) && filename[0] != '\0' && s == writefile_list))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001811 break;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001812 answer = charealloc(answer, xend + 2);
David Lawrence Ramsey9eff7462003-09-16 02:04:00 +00001813 charmove(answer + x + 1, answer + x, xend - x + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001814 xend++;
1815 answer[x] = kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001816 x++;
1817
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001818#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001819 fprintf(stderr, "input \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001820#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00001821 } /* switch (kbinput) */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00001822#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00001823 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00001824#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001825 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001826 wrefresh(bottomwin);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001827 } /* while (kbinput ...) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001828
Chris Allegretta5af58892003-01-17 21:07:38 +00001829 /* We finished putting in an answer; reset x */
1830 x = -1;
1831
Chris Allegretta7662c862003-01-13 01:35:15 +00001832 /* Just check for a blank answer here */
Chris Allegretta15c28f82003-01-05 21:47:06 +00001833 if (answer[0] == '\0')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001834 return -2;
1835 else
1836 return 0;
1837}
1838
Chris Allegrettaf717f982003-02-13 22:25:01 +00001839void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001840{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001841 size_t space;
1842 /* The space we have available for display. */
1843 size_t verlen = strlen(VERMSG) + 1;
1844 /* The length of the version message. */
1845 const char *prefix;
1846 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
1847 size_t prefixlen;
1848 /* strlen(prefix) + 1. */
1849 const char *state;
1850 /* "Modified", "View", or spaces the length of "Modified".
1851 * Tells the state of this buffer. */
1852 size_t statelen = 0;
1853 /* strlen(state) + 1. */
1854 char *exppath = NULL;
1855 /* The file name, expanded for display. */
1856 size_t explen = 0;
1857 /* strlen(exppath) + 1. */
1858 int newbuffer = FALSE;
1859 /* Do we say "New Buffer"? */
1860 int dots = FALSE;
1861 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001862
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001863 assert(path != NULL || filename != NULL);
1864 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001865
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001866 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001867
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001868 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001869
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001870 if (COLS <= 5 || COLS - 5 < verlen)
1871 space = 0;
1872 else {
1873 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00001874 /* Reserve 2/3 of the screen plus one column for after the
1875 * version message. */
1876 if (space < COLS - (COLS / 3) + 1)
1877 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001878 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001879
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001880 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00001881 /* The version message should only take up 1/3 of the screen
1882 * minus one column. */
1883 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001884 waddstr(topwin, " ");
1885 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001886
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001887 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001888 state = _("Modified");
1889 else if (path == NULL && ISSET(VIEW_MODE))
1890 state = _("View");
1891 else {
1892 if (space > 0)
1893 statelen = strnlen(_("Modified"), space - 1) + 1;
1894 state = &hblank[COLS - statelen];
1895 }
1896 statelen = strnlen(state, COLS);
1897 /* We need a space before state. */
1898 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
1899 statelen++;
1900
1901 assert(space >= 0);
1902 if (space == 0 || statelen >= space)
1903 goto the_end;
1904
1905#ifndef DISABLE_BROWSER
1906 if (path != NULL)
1907 prefix = _("DIR:");
1908 else
1909#endif
1910 if (filename[0] == '\0') {
1911 prefix = _("New Buffer");
1912 newbuffer = TRUE;
1913 } else
1914 prefix = _("File:");
1915 assert(statelen < space);
1916 prefixlen = strnlen(prefix, space - statelen);
1917 /* If newbuffer is FALSE, we need a space after prefix. */
1918 if (!newbuffer && prefixlen + statelen < space)
1919 prefixlen++;
1920
1921 if (path == NULL)
1922 path = filename;
David Lawrence Ramsey1dcf36a2004-05-23 21:17:56 +00001923 space -= prefixlen + statelen;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001924 /* space is now the room we have for the file name. */
1925 if (!newbuffer) {
1926 size_t lenpt = strlenpt(path), start_col;
1927
1928 if (lenpt > space)
1929 start_col = actual_x(path, lenpt - space);
1930 else
1931 start_col = 0;
1932 exppath = display_string(path, start_col, space);
1933 dots = (lenpt > space);
1934 explen = strlen(exppath);
1935 }
1936
1937 if (!dots) {
1938 /* There is room for the whole filename, so we center it. */
1939 waddnstr(topwin, hblank, (space - explen) / 3);
1940 waddnstr(topwin, prefix, prefixlen);
1941 if (!newbuffer) {
1942 assert(strlen(prefix) + 1 == prefixlen);
1943 waddch(topwin, ' ');
1944 waddstr(topwin, exppath);
1945 }
1946 } else {
1947 /* We will say something like "File: ...ename". */
1948 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramsey1dcf36a2004-05-23 21:17:56 +00001949 if (space <= 0 || newbuffer)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001950 goto the_end;
1951 waddch(topwin, ' ');
1952 waddnstr(topwin, "...", space);
1953 if (space <= 3)
1954 goto the_end;
1955 space -= 3;
1956 assert(explen = space + 3);
1957 waddnstr(topwin, exppath + 3, space);
1958 }
1959
1960 the_end:
1961
1962 free(exppath);
1963
1964 if (COLS <= 1 || statelen >= COLS - 1)
1965 mvwaddnstr(topwin, 0, 0, state, COLS);
1966 else {
1967 assert(COLS - statelen - 2 >= 0);
1968 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
1969 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
1970 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00001971
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001972 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001973
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001974 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001975 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001976 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001977}
1978
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001979/* If modified is not already set, set it and update titlebar. */
1980void set_modified(void)
1981{
1982 if (!ISSET(MODIFIED)) {
1983 SET(MODIFIED);
1984 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001985 }
1986}
1987
1988void statusbar(const char *msg, ...)
1989{
1990 va_list ap;
1991
1992 va_start(ap, msg);
1993
1994 /* Curses mode is turned off. If we use wmove() now, it will muck
1995 * up the terminal settings. So we just use vfprintf(). */
1996 if (curses_ended) {
1997 vfprintf(stderr, msg, ap);
1998 va_end(ap);
1999 return;
2000 }
2001
2002 /* Blank out the line. */
2003 blank_statusbar();
2004
2005 if (COLS >= 4) {
2006 char *bar;
2007 char *foo;
2008 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002009#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2010 int old_whitespace = ISSET(WHITESPACE_DISPLAY);
2011 UNSET(WHITESPACE_DISPLAY);
2012#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002013 bar = charalloc(COLS - 3);
2014 vsnprintf(bar, COLS - 3, msg, ap);
2015 va_end(ap);
2016 foo = display_string(bar, 0, COLS - 4);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002017#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2018 if (old_whitespace)
2019 SET(WHITESPACE_DISPLAY);
2020#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002021 free(bar);
2022 foo_len = strlen(foo);
2023 start_x = (COLS - foo_len - 4) / 2;
2024
2025 wmove(bottomwin, 0, start_x);
2026 wattron(bottomwin, A_REVERSE);
2027
2028 waddstr(bottomwin, "[ ");
2029 waddstr(bottomwin, foo);
2030 free(foo);
2031 waddstr(bottomwin, " ]");
2032 wattroff(bottomwin, A_REVERSE);
2033 wnoutrefresh(bottomwin);
2034 reset_cursor();
2035 wrefresh(edit);
2036 /* Leave the cursor at its position in the edit window, not
2037 * in the statusbar. */
2038 }
2039
2040 SET(DISABLE_CURPOS);
2041 statblank = 26;
2042}
2043
Chris Allegretta6232d662002-05-12 19:52:15 +00002044void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002045{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002046 size_t i, colwidth, slen;
2047 char *keystr;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002048
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002049 if (ISSET(NO_HELP))
2050 return;
2051
Chris Allegretta6232d662002-05-12 19:52:15 +00002052 if (s == main_list) {
2053 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002054 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002055 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002056 slen = length_of_list(s);
2057
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002058 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002059 if (slen > MAIN_VISIBLE)
2060 slen = MAIN_VISIBLE;
2061 }
2062
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002063 /* There will be this many characters per column. We need at least
2064 * 3 to display anything properly.*/
2065 colwidth = COLS / ((slen / 2) + (slen % 2));
2066 keystr = charalloc(colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002067
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002068 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002069
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002070 for (i = 0; i < slen; i++, s = s->next) {
2071 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
Chris Allegretta658399a2001-06-14 02:54:22 +00002072
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002073 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002074#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002075 if (s->ctrlval == NANO_HISTORY_KEY)
2076 strncpy(keystr, _("Up"), colwidth);
2077 else
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002078#endif
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002079 if (s->ctrlval == NANO_CONTROL_SPACE)
2080 strncpy(keystr, "^ ", colwidth);
2081 else if (s->ctrlval == NANO_CONTROL_8)
2082 strncpy(keystr, "^?", colwidth);
2083 /* Normal values. Assume that the shortcut has an equivalent
2084 * control key, meta key sequence, or both. */
2085 else if (s->ctrlval != NANO_NO_KEY)
2086 snprintf(keystr, colwidth, "^%c", s->ctrlval + 64);
2087 else if (s->metaval != NANO_NO_KEY)
2088 snprintf(keystr, colwidth, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00002089
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002090 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002091 }
2092
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002093 free(keystr);
2094
2095 wnoutrefresh(bottomwin);
2096 reset_cursor();
2097 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002098}
2099
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002100/* Write a shortcut key to the help area at the bottom of the window.
2101 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2102 * to write at most len characters, even if len is very small and
2103 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2104 * the whole string! We do not bother padding the entry with blanks. */
2105void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002106{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002107 assert(keystroke != NULL && desc != NULL && len >= 0);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002108 wattron(bottomwin, A_REVERSE);
2109 waddnstr(bottomwin, keystroke, len);
2110 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002111 len -= strlen(keystroke) + 1;
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002112 if (len > 0) {
2113 waddch(bottomwin, ' ');
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002114 waddnstr(bottomwin, desc, len);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002115 }
2116}
2117
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002118/* And so start the display update routines. */
2119
2120#ifndef NDEBUG
2121int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002122{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002123 int check_line = 0;
2124 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002125
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002126 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
2127 check_line++;
2128 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002129}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002130#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00002131
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002132/* nano scrolls horizontally within a line in chunks. This function
2133 * returns the column number of the first character displayed in the
2134 * window when the cursor is at the given column. Note that
2135 * 0 <= column - get_page_start(column) < COLS. */
2136size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002137{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002138 assert(COLS > 0);
2139 if (column == 0 || column < COLS - 1)
2140 return 0;
2141 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002142 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002143 else if (COLS > 2)
2144 return column - (COLS - 2);
2145 else
2146 return column - (COLS - 1);
2147 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002148}
2149
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002150/* Resets current_y, based on the position of current, and puts the
2151 * cursor at (current_y, current_x). */
2152void reset_cursor(void)
2153{
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002154 /* Yuck. This condition can be true after open_file() when opening
2155 * the first file. */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002156 if (edittop == NULL)
2157 return;
2158
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002159 current_y = current->lineno - edittop->lineno;
2160 if (current_y < editwinrows) {
2161 size_t x = xplustabs();
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002162
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002163 wmove(edit, current_y, x - get_page_start(x));
2164 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002165}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002166
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002167/* edit_add() takes care of the job of actually painting a line into the
2168 * edit window. fileptr is the line to be painted, at row yval of the
2169 * window. converted is the actual string to be written to the window,
2170 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00002171 * characters. start is the column number of the first character of
2172 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002173 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002174void edit_add(const filestruct *fileptr, const char *converted, int
2175 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002176{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002177#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
2178 size_t startpos = actual_x(fileptr->data, start);
2179 /* The position in fileptr->data of the leftmost character
2180 * that displays at least partially on the window. */
2181 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2182 /* The position in fileptr->data of the first character that is
2183 * completely off the window to the right.
2184 *
2185 * Note that endpos might be beyond the null terminator of the
2186 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002187#endif
2188
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002189 assert(fileptr != NULL && converted != NULL);
2190 assert(strlen(converted) <= COLS);
2191
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002192 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002193 * just the text that needs it). */
2194 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002195
Chris Allegretta7dd77682001-12-08 19:52:28 +00002196#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00002197 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002198 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002199
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002200 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2201 int x_start;
2202 /* Starting column for mvwaddnstr. Zero-based. */
2203 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002204 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002205 * characters on a whole line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002206 regmatch_t startmatch; /* match position for start_regexp */
2207 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002208
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002209 if (tmpcolor->bright)
2210 wattron(edit, A_BOLD);
2211 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002212 /* Two notes about regexec(). Return value 0 means there is
2213 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002214 * after the match. */
2215
2216 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002217 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002218 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002219
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002220 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002221 * last match. Even though two matches may overlap, we
2222 * want to ignore them, so that we can highlight
2223 * C-strings correctly. */
2224 while (k < endpos) {
2225 /* Note the fifth parameter to regexec(). It says
2226 * not to match the beginning-of-line character
2227 * unless k is 0. If regexec() returns REG_NOMATCH,
2228 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00002229 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002230 &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002231 break;
2232 /* Translate the match to the beginning of the line. */
2233 startmatch.rm_so += k;
2234 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002235 if (startmatch.rm_so == startmatch.rm_eo) {
2236 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00002237 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002238 } else if (startmatch.rm_so < endpos &&
2239 startmatch.rm_eo > startpos) {
2240 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002241 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002242 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002243 x_start = strnlenpt(fileptr->data,
2244 startmatch.rm_so) - start;
2245 paintlen = strnlenpt(fileptr->data,
2246 startmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002247 if (paintlen > COLS - x_start)
2248 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002249
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002250 assert(0 <= x_start && 0 < paintlen &&
2251 x_start + paintlen <= COLS);
2252 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002253 converted + x_start, paintlen);
2254 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002255 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002256 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002257 } else {
2258 /* This is a multi-line regexp. There are two steps.
2259 * First, we have to see if the beginning of the line is
2260 * colored by a start on an earlier line, and an end on
2261 * this line or later.
2262 *
2263 * We find the first line before fileptr matching the
2264 * start. If every match on that line is followed by an
2265 * end, then go to step two. Otherwise, find the next line
2266 * after start_line matching the end. If that line is not
2267 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002268
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002269 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002270 /* the first line before fileptr matching start */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002271 regoff_t start_col;
2272 /* where it starts in that line */
2273 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002274
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002275 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00002276 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002277 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002278 /* If there is an end on this line, there is no need
2279 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002280 if (regexec(tmpcolor->end, start_line->data, 0,
2281 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002282 goto step_two;
2283 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002284 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002285 /* No start found, so skip to the next step. */
2286 if (start_line == NULL)
2287 goto step_two;
2288 /* Now start_line is the first line before fileptr
2289 * containing a start match. Is there a start on this
2290 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002291
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002292 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002293 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002294 start_col += startmatch.rm_so;
2295 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002296 if (regexec(tmpcolor->end,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002297 start_line->data + start_col + startmatch.rm_eo,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002298 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
2299 REG_NOTBOL) == REG_NOMATCH)
2300 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002301 break;
2302 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002303 if (regexec(&tmpcolor->start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002304 start_line->data + start_col, 1,
2305 &startmatch, REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002306 /* No later start on this line. */
2307 goto step_two;
2308 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002309 /* Indeed, there is a start not followed on this line by
2310 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002311
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002312 /* We have already checked that there is no end before
2313 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002314 * the start at all? We don't paint unterminated
2315 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002316 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002317 while (end_line != NULL &&
2318 regexec(tmpcolor->end, end_line->data, 1, &endmatch, 0))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002319 end_line = end_line->next;
2320
2321 /* No end found, or it is too early. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002322 if (end_line == NULL ||
2323 (end_line == fileptr && endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002324 goto step_two;
2325
2326 /* Now paint the start of fileptr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002327 paintlen = end_line != fileptr ? COLS :
2328 strnlenpt(fileptr->data, endmatch.rm_eo) - start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002329 if (paintlen > COLS)
2330 paintlen = COLS;
2331
2332 assert(0 < paintlen && paintlen <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002333 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002334
2335 /* We have already painted the whole line. */
2336 if (paintlen == COLS)
2337 goto skip_step_two;
2338
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002339 step_two:
2340 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002341 start_col = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002342 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002343 if (regexec(&tmpcolor->start,
2344 fileptr->data + start_col, 1, &startmatch,
2345 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
2346 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002347 /* No more starts on this line. */
2348 break;
2349 /* Translate the match to be relative to the
2350 * beginning of the line. */
2351 startmatch.rm_so += start_col;
2352 startmatch.rm_eo += start_col;
2353
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002354 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002355 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002356 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002357 x_start = strnlenpt(fileptr->data,
2358 startmatch.rm_so) - start;
2359 if (regexec(tmpcolor->end,
2360 fileptr->data + startmatch.rm_eo, 1, &endmatch,
2361 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002362 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002363 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002364 endmatch.rm_so += startmatch.rm_eo;
2365 endmatch.rm_eo += startmatch.rm_eo;
2366 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002367 * appear on this page, and is the match more
2368 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002369 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002370 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002371 paintlen = strnlenpt(fileptr->data,
2372 endmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002373 if (x_start + paintlen > COLS)
2374 paintlen = COLS - x_start;
2375
2376 assert(0 <= x_start && 0 < paintlen &&
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002377 x_start + paintlen <= COLS);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002378 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002379 converted + x_start, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002380 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002381 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002382 /* There is no end on this line. But we haven't
2383 * yet looked for one on later lines. */
2384 end_line = fileptr->next;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002385 while (end_line != NULL &&
2386 regexec(tmpcolor->end, end_line->data, 0,
2387 NULL, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002388 end_line = end_line->next;
2389 if (end_line != NULL) {
2390 assert(0 <= x_start && x_start < COLS);
2391 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002392 converted + x_start, COLS - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002393 /* We painted to the end of the line, so
2394 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002395 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002396 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002397 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002398 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002399 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002400 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002401
Chris Allegrettace452fb2003-02-03 02:56:44 +00002402 skip_step_two:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002403 wattroff(edit, A_BOLD);
2404 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
2405 } /* for tmpcolor in colorstrings */
2406 }
Chris Allegretta598106e2002-01-19 01:59:37 +00002407#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002408
Chris Allegretta7dd77682001-12-08 19:52:28 +00002409#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002410 if (ISSET(MARK_ISSET)
2411 && (fileptr->lineno <= mark_beginbuf->lineno
2412 || fileptr->lineno <= current->lineno)
2413 && (fileptr->lineno >= mark_beginbuf->lineno
2414 || fileptr->lineno >= current->lineno)) {
2415 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002416
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002417 const filestruct *top;
2418 /* Either current or mark_beginbuf, whichever is first. */
2419 size_t top_x;
2420 /* current_x or mark_beginx, corresponding to top. */
2421 const filestruct *bot;
2422 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002423 int x_start;
2424 /* Starting column for mvwaddnstr. Zero-based. */
2425 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002426 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002427 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002428
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002429 mark_order(&top, &top_x, &bot, &bot_x);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002430
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002431 if (top->lineno < fileptr->lineno || top_x < startpos)
2432 top_x = startpos;
2433 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2434 bot_x = endpos;
2435
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002436 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002437 if (top_x < endpos && bot_x > startpos) {
2438 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002439
2440 /* x_start is the expanded location of the beginning of the
2441 * mark minus the beginning of the page. */
2442 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002443
2444 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002445 /* If the end of the mark is off the page, paintlen is
2446 * -1, meaning that everything on the line gets
2447 * painted. */
2448 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002449 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002450 /* Otherwise, paintlen is the expanded location of the
2451 * end of the mark minus the expanded location of the
2452 * beginning of the mark. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002453 paintlen = strnlenpt(fileptr->data, bot_x)
2454 - (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002455
2456 /* If x_start is before the beginning of the page, shift
2457 * paintlen x_start characters to compensate, and put
2458 * x_start at the beginning of the page. */
2459 if (x_start < 0) {
2460 paintlen += x_start;
2461 x_start = 0;
2462 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002463
2464 assert(x_start >= 0 && x_start <= strlen(converted));
2465
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002466 wattron(edit, A_REVERSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002467 mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002468 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002469 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002470 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002471#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002472}
2473
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002474/* Just update one line in the edit buffer. Basically a wrapper for
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002475 * edit_add().
2476 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002477 * If fileptr != current, then index is considered 0. The line will be
2478 * displayed starting with fileptr->data[index]. Likely args are
2479 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002480void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002481{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002482 int line;
2483 /* line in the edit window for CURSES calls */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002484 char *converted;
2485 /* fileptr->data converted to have tabs and control characters
2486 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002487 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002488
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002489 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002490
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002491 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002492
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002493 /* We assume the line numbers are valid. Is that really true? */
2494 assert(line < 0 || line == check_linenumbers(fileptr));
2495
2496 if (line < 0 || line >= editwinrows)
2497 return;
2498
2499 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002500 mvwaddstr(edit, line, 0, hblank);
2501
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002502 /* Next, convert variables that index the line to their equivalent
2503 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002504 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002505 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002506
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002507 /* Expand the line, replacing Tab by spaces, and control characters
2508 * by their display form. */
2509 converted = display_string(fileptr->data, page_start, COLS);
Robert Siemborski53875912000-06-16 04:25:30 +00002510
Chris Allegretta4dc03d52002-05-11 03:04:44 +00002511 /* Now, paint the line */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002512 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002513 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002514
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002515 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002516 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002517 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002518 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002519}
2520
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002521/* Return a nonzero value if we need an update after moving
2522 * horizontally. We need one if the mark is on or if old_pww and
2523 * placewewant are on different pages. Assume none of the text has
2524 * changed since the last update. */
2525int need_horizontal_update(int old_pww)
2526{
2527 return
2528#ifndef NANO_SMALL
2529 ISSET(MARK_ISSET) ||
2530#endif
2531 get_page_start(old_pww) != get_page_start(placewewant);
2532}
2533
2534/* Return a nonzero value if we need an update after moving vertically.
2535 * We need one if the mark is on or if old_pww and placewewant
2536 * are on different pages. Assume none of the text has changed since
2537 * the last update. */
2538int need_vertical_update(int old_pww)
2539{
2540 return
2541#ifndef NANO_SMALL
2542 ISSET(MARK_ISSET) ||
2543#endif
2544 get_page_start(old_pww) != get_page_start(placewewant);
2545}
2546
2547/* Scroll the edit window in the given direction and the given number
2548 * of lines, and draw new lines on the blank lines left after the
2549 * scrolling. direction is the direction to scroll, either UP or DOWN,
2550 * and nlines is the number of lines to scroll. Don't redraw the old
2551 * topmost or bottommost line (where we assume current is) before
2552 * scrolling or draw the new topmost or bottommost line after scrolling
2553 * (where we assume current will be), since we don't know where we are
2554 * on the page or whether we'll stay there. Assume none of the text has
2555 * changed since the last update. */
2556void edit_scroll(updown direction, int nlines)
2557{
2558 filestruct *foo;
2559 int i, scroll_rows = 0;
2560
2561 /* Scrolling less than one line or more than editwinrows lines is
2562 * redundant, so don't allow it. */
2563 if (nlines < 1 || nlines > editwinrows)
2564 return;
2565
2566 /* Move the top line of the edit window up or down (depending on the
2567 * value of direction) nlines lines. If there are fewer lines of
2568 * text than that left, move it to the top or bottom line of the
2569 * file (depending on the value of direction). Keep track of
2570 * how many lines we moved in scroll_rows. */
2571 for (i = nlines; i > 0; i--) {
2572 if (direction == UP) {
2573 if (edittop->prev == NULL)
2574 break;
2575 edittop = edittop->prev;
2576 scroll_rows--;
2577 } else {
2578 if (edittop->next == NULL)
2579 break;
2580 edittop = edittop->next;
2581 scroll_rows++;
2582 }
2583 }
2584
2585 /* Scroll the text on the screen up or down scroll_rows lines,
2586 * depending on the value of direction. */
2587 scrollok(edit, TRUE);
2588 wscrl(edit, scroll_rows);
2589 scrollok(edit, FALSE);
2590
2591 foo = edittop;
2592 if (direction != UP) {
2593 int slines = editwinrows - nlines;
2594 for (; slines > 0 && foo != NULL; slines--)
2595 foo = foo->next;
2596 }
2597
2598 /* And draw new lines on the blank top or bottom lines of the edit
2599 * window, depending on the value of direction. Don't draw the new
2600 * topmost or new bottommost line. */
2601 while (scroll_rows != 0 && foo != NULL) {
2602 if (foo->next != NULL)
2603 update_line(foo, 0);
2604 if (direction == UP)
2605 scroll_rows++;
2606 else
2607 scroll_rows--;
2608 foo = foo->next;
2609 }
2610}
2611
2612/* Update any lines between old_current and current that need to be
2613 * updated. Note that we use placewewant to determine whether we need
2614 * updates and current_x to update current, so if placewewant needs to
2615 * be changed, it should be changed after calling this, and if current_x
2616 * needs to be changed, it should be changed before calling this.
2617 * Assume none of the text has changed since the last update. */
2618void edit_redraw(const filestruct *old_current)
2619{
2620 int do_refresh = need_vertical_update(0);
2621 const filestruct *foo;
2622
2623 /* If either old_current or current is offscreen, refresh the screen
2624 * and get out. */
2625 if (old_current->lineno < edittop->lineno || old_current->lineno >=
2626 edittop->lineno + editwinrows || current->lineno <
2627 edittop->lineno || current->lineno >= edittop->lineno +
2628 editwinrows) {
2629 edit_refresh();
2630 return;
2631 }
2632
2633 /* Update old_current and current if we're not on the first page.
2634 * If the mark is on, update all the lines between old_current and
2635 * current too. */
2636 foo = old_current;
2637 while (foo != current) {
2638 if (do_refresh)
2639 update_line(foo, 0);
2640#ifndef NANO_SMALL
2641 if (!ISSET(MARK_ISSET))
2642#endif
2643 break;
2644 if (foo->lineno > current->lineno)
2645 foo = foo->prev;
2646 else
2647 foo = foo->next;
2648 }
2649 if (do_refresh)
2650 update_line(current, current_x);
2651}
2652
Chris Allegretta6df90f52002-07-19 01:08:59 +00002653/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002654void edit_refresh(void)
2655{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002656 /* Neither of these conditions should occur, but they do. edittop
2657 * is NULL when you open an existing file on the command line, and
Chris Allegretta6df90f52002-07-19 01:08:59 +00002658 * ENABLE_COLOR is defined. Yuck. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002659 if (current == NULL)
2660 return;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002661 if (edittop == NULL)
2662 edittop = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002663
Chris Allegretta63d0b482003-01-26 19:47:10 +00002664 if (current->lineno < edittop->lineno ||
2665 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002666 /* Note that edit_update() changes edittop so that
2667 * current->lineno = edittop->lineno + editwinrows / 2. Thus
2668 * when it then calls edit_refresh(), there is no danger of
2669 * getting an infinite loop. */
Chris Allegrettada721be2000-07-31 01:26:42 +00002670 edit_update(current, CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002671 else {
2672 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002673 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002674
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002675#ifdef DEBUG
2676 fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", edittop->lineno);
2677#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002678
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002679 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00002680 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002681 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002682 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002683 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002684 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002685 }
2686 while (nlines < editwinrows) {
2687 mvwaddstr(edit, nlines, 0, hblank);
2688 nlines++;
2689 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002690 reset_cursor();
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002691
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002692 /* What the hell are we expecting to update the screen if this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002693 * isn't here? Luck? */
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002694 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002695 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002696}
2697
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002698/* Nice generic routine to update the edit buffer, given a pointer to the
2699 * file struct =) */
David Lawrence Ramsey1356a0a2003-09-10 20:31:02 +00002700void edit_update(filestruct *fileptr, topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002701{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002702 if (fileptr == NULL)
2703 return;
2704
Chris Allegretta6df90f52002-07-19 01:08:59 +00002705 if (location != TOP) {
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002706 int goal = (location == NONE) ? current_y : editwinrows / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002707
David Lawrence Ramseyd91ab6e2003-09-07 23:57:24 +00002708 for (; goal > 0 && fileptr->prev != NULL; goal--)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002709 fileptr = fileptr->prev;
2710 }
2711 edittop = fileptr;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002712 edit_refresh();
2713}
2714
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002715/* Ask a question on the statusbar. Answer will be stored in answer
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002716 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
Chris Allegretta88520c92001-05-05 17:45:54 +00002717 * otherwise, the valid shortcut key caught. Def is any editable text we
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002718 * want to put up by default.
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002719 *
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002720 * New arg tabs tells whether or not to allow tab completion. */
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002721int statusq(int allowtabs, const shortcut *s, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002722#ifndef NANO_SMALL
2723 historyheadtype *which_history,
2724#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00002725 const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002726{
2727 va_list ap;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002728 char *foo = charalloc(COLS - 3);
Chris Allegretta9caa1932002-02-15 20:08:05 +00002729 int ret;
Chris Allegretta2084acc2001-11-29 03:43:08 +00002730#ifndef DISABLE_TABCOMP
Chris Allegrettaa16e4e92002-01-05 18:59:54 +00002731 int list = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00002732#endif
2733
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002734 bottombars(s);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002735
2736 va_start(ap, msg);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002737 vsnprintf(foo, COLS - 4, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002738 va_end(ap);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002739 foo[COLS - 4] = '\0';
Chris Allegretta8ce24132001-04-30 11:28:46 +00002740
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002741 ret = nanogetstr(allowtabs, foo, def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002742#ifndef NANO_SMALL
2743 which_history,
Chris Allegretta2084acc2001-11-29 03:43:08 +00002744#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002745 s
2746#ifndef DISABLE_TABCOMP
2747 , &list
2748#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002749 );
Chris Allegretta6df90f52002-07-19 01:08:59 +00002750 free(foo);
Chris Allegretta65f075d2003-02-13 03:03:49 +00002751 resetstatuspos = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002752
2753 switch (ret) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002754 case NANO_FIRSTLINE_KEY:
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002755 case NANO_FIRSTLINE_FKEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002756 do_first_line();
Chris Allegretta65f075d2003-02-13 03:03:49 +00002757 resetstatuspos = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002758 break;
2759 case NANO_LASTLINE_KEY:
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002760 case NANO_LASTLINE_FKEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002761 do_last_line();
Chris Allegretta65f075d2003-02-13 03:03:49 +00002762 resetstatuspos = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002763 break;
David Lawrence Ramsey8faf3052003-09-04 20:25:29 +00002764#ifndef DISABLE_JUSTIFY
2765 case NANO_PARABEGIN_KEY:
2766 do_para_begin();
2767 resetstatuspos = 1;
2768 break;
2769 case NANO_PARAEND_KEY:
2770 do_para_end();
2771 resetstatuspos = 1;
2772 break;
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002773 case NANO_FULLJUSTIFY_KEY:
David Lawrence Ramseyd12fd4b2004-05-28 15:05:56 +00002774 if (!ISSET(VIEW_MODE))
2775 do_full_justify();
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002776 resetstatuspos = 1;
2777 break;
David Lawrence Ramsey8faf3052003-09-04 20:25:29 +00002778#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002779 case NANO_CANCEL_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00002780 ret = -1;
Chris Allegretta65f075d2003-02-13 03:03:49 +00002781 resetstatuspos = 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002782 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002783 }
Chris Allegrettaa90d0cf2003-02-10 02:55:03 +00002784 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002785
2786#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002787 fprintf(stderr, "I got \"%s\"\n", answer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002788#endif
2789
Chris Allegretta6df90f52002-07-19 01:08:59 +00002790#ifndef DISABLE_TABCOMP
2791 /* if we've done tab completion, there might be a list of
2792 filename matches on the edit window at this point; make sure
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002793 they're cleared off. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002794 if (list)
2795 edit_refresh();
2796#endif
2797
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002798 return ret;
2799}
2800
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002801/* Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002802 * for N, 2 for All (if all is nonzero when passed in) and -1 for abort
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002803 * (^C). */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002804int do_yesno(int all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002805{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002806 int ok = -2, width = 16;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002807 const char *yesstr; /* String of yes characters accepted */
2808 const char *nostr; /* Same for no */
2809 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00002810
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002811 /* Yes, no and all are strings of any length. Each string consists
2812 * of all characters accepted as a valid character for that value.
2813 * The first value will be the one displayed in the shortcuts. */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002814 yesstr = _("Yy");
2815 nostr = _("Nn");
2816 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002817
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002818 /* Remove gettext() call for keybindings until we clear the thing
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002819 * up. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002820 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002821 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00002822
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002823 if (COLS < 32)
2824 width = COLS / 2;
2825
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002826 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00002827 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002828
Chris Allegretta6232d662002-05-12 19:52:15 +00002829 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00002830 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002831 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002832
2833 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002834 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00002835 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002836 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002837 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002838
Chris Allegrettadb28e962003-01-28 01:23:40 +00002839 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00002840 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002841 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002842
Chris Allegrettadb28e962003-01-28 01:23:40 +00002843 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002844 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002845 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00002846
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002847 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002848
2849 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002850 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002851
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002852 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002853
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002854 wrefresh(bottomwin);
2855
Chris Allegrettadb28e962003-01-28 01:23:40 +00002856 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002857 int kbinput;
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00002858 int meta_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00002859#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002860 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00002861#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002862
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00002863 kbinput = get_kbinput(edit, &meta_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002864
2865 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00002866 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00002867#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002868 /* Look ma! We get to duplicate lots of code from
2869 * do_mouse()!! */
2870 else if (kbinput == KEY_MOUSE) {
2871 kbinput = get_mouseinput(&mouse_x, &mouse_y, 0);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002872
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002873 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
2874 wenclose(bottomwin, mouse_y, mouse_x) && mouse_x <
2875 (width * 2) && mouse_y >= editwinrows + 3) {
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002876
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002877 int x = mouse_x / width;
2878 /* Did we click in the first column of shortcuts, or
2879 * the second? */
2880 int y = mouse_y - editwinrows - 3;
2881 /* Did we click in the first row of shortcuts? */
2882
2883 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
2884
2885 /* x = 0 means they clicked Yes or No.
2886 * y = 0 means Yes or All. */
2887 ok = -2 * x * y + x - y + 1;
2888
2889 if (ok == 2 && !all)
2890 ok = -2;
2891 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002892 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00002893#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002894 /* Look for the kbinput in the yes, no and (optionally) all
2895 * str. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00002896 else if (strchr(yesstr, kbinput) != NULL)
2897 ok = 1;
2898 else if (strchr(nostr, kbinput) != NULL)
2899 ok = 0;
2900 else if (all && strchr(allstr, kbinput) != NULL)
2901 ok = 2;
2902 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002903
Chris Allegrettadb28e962003-01-28 01:23:40 +00002904 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002905}
2906
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002907int total_refresh(void)
2908{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002909 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002910 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002911 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002912 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002913 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002914 wnoutrefresh(bottomwin);
2915 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002916 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002917 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002918 clearok(bottomwin, FALSE);
2919 edit_refresh();
2920 titlebar(NULL);
2921 return 1;
2922}
2923
2924void display_main_list(void)
2925{
2926 bottombars(main_list);
2927}
2928
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002929/* If constant is FALSE, the user typed ^C so we unconditionally display
Chris Allegrettad26ab912003-01-28 01:16:47 +00002930 * the cursor position. Otherwise, we display it only if the character
2931 * position changed, and DISABLE_CURPOS is not set.
2932 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002933 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
2934 * old_i and old_totsize. That way, we leave the current statusbar
2935 * alone, but next time we will display. */
Chris Allegretta2084acc2001-11-29 03:43:08 +00002936int do_cursorpos(int constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002937{
Chris Allegrettad26ab912003-01-28 01:16:47 +00002938 const filestruct *fileptr;
2939 unsigned long i = 0;
2940 static unsigned long old_i = 0;
2941 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002942
Chris Allegrettad26ab912003-01-28 01:16:47 +00002943 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00002944
2945 if (old_totsize == -1)
2946 old_totsize = totsize;
2947
Chris Allegrettad26ab912003-01-28 01:16:47 +00002948 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
2949 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00002950 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00002951 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00002952 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00002953
Chris Allegrettad26ab912003-01-28 01:16:47 +00002954 if (constant && ISSET(DISABLE_CURPOS)) {
2955 UNSET(DISABLE_CURPOS);
2956 old_i = i;
2957 old_totsize = totsize;
2958 return 0;
2959 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00002960
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00002961 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002962 * unconditionally; otherwise, only display the position when the
2963 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00002964 if (!constant || old_i != i || old_totsize != totsize) {
2965 unsigned long xpt = xplustabs() + 1;
2966 unsigned long cur_len = strlenpt(current->data) + 1;
2967 int linepct = 100 * current->lineno / totlines;
2968 int colpct = 100 * xpt / cur_len;
2969 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
2970
2971 statusbar(
2972 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
2973 current->lineno, totlines, linepct,
2974 xpt, cur_len, colpct,
2975 i, totsize, bytepct);
2976 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00002977 }
2978
2979 old_i = i;
2980 old_totsize = totsize;
2981
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002982 reset_cursor();
Chris Allegrettad26ab912003-01-28 01:16:47 +00002983 return 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002984}
2985
Chris Allegretta2084acc2001-11-29 03:43:08 +00002986int do_cursorpos_void(void)
2987{
2988 return do_cursorpos(0);
2989}
2990
Chris Allegretta4640fe32003-02-10 03:10:03 +00002991/* Calculate the next line of help_text, starting at ptr. */
2992int line_len(const char *ptr)
2993{
2994 int j = 0;
2995
2996 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
2997 ptr++;
2998 j++;
2999 }
3000 if (j == COLS - 5) {
3001 /* Don't wrap at the first of two spaces following a period. */
3002 if (*ptr == ' ' && *(ptr + 1) == ' ')
3003 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003004 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003005 while (*ptr != ' ' && j > 0) {
3006 ptr--;
3007 j--;
3008 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003009 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003010 if (j == 0)
3011 j = COLS - 5;
3012 }
3013 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
3014 return j;
3015}
3016
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003017#ifndef DISABLE_HELP
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003018/* Our shortcut-list-compliant help function, which is better than
3019 * nothing, and dynamic! */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003020int do_help(void)
3021{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003022 int line = 0;
3023 /* The line number in help_text of the first displayed help line.
3024 * This variable is zero-based. */
3025 int no_more = 0;
3026 /* no_more means the end of the help text is shown, so don't go down
3027 * any more. */
3028 int kbinput = ERR, meta_key;
3029
3030 int no_help_flag = ISSET(NO_HELP);
3031 int old_cursor = curs_set(0);
3032#ifndef DISABLE_MOUSE
3033 const shortcut *oldshortcut = currshortcut;
3034 /* We will set currshortcut to allow clicking on the help
3035 screen shortcut list. */
3036#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003037
3038 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003039 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003040 blank_statusbar();
3041
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003042 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003043 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003044 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003045
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003046#ifndef DISABLE_MOUSE
3047 /* Set currshortcut to allow clicking on the help screen shortcut
3048 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003049 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003050#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003051
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003052 if (ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003053 /* Well, if we're going to do this, we should at least do it the
3054 * right way. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003055 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003056 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003057 }
3058 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003059
3060 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003061 int i;
3062 int old_line = line;
3063 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003064 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003065
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003066 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003067#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003068 case KEY_MOUSE:
3069 do_mouse();
3070 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003071#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003072 case NANO_NEXTPAGE_KEY:
3073 case NANO_NEXTPAGE_FKEY:
3074 if (!no_more)
3075 line += editwinrows - 2;
3076 break;
3077 case NANO_PREVPAGE_KEY:
3078 case NANO_PREVPAGE_FKEY:
3079 if (line > 0) {
3080 line -= editwinrows - 2;
3081 if (line < 0)
3082 line = 0;
3083 }
3084 break;
3085 case NANO_PREVLINE_KEY:
3086 if (line > 0)
3087 line--;
3088 break;
3089 case NANO_NEXTLINE_KEY:
3090 if (!no_more)
3091 line++;
3092 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003093 }
3094
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003095 if (line == old_line && kbinput != ERR)
3096 goto skip_redisplay;
3097
3098 blank_edit();
3099
3100 assert(COLS > 5);
3101
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003102 /* Calculate where in the text we should be, based on the
3103 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003104 for (i = 0; i < line; i++) {
Chris Allegretta4640fe32003-02-10 03:10:03 +00003105 ptr += line_len(ptr);
3106 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003107 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003108 }
3109
Chris Allegretta4640fe32003-02-10 03:10:03 +00003110 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
3111 int j = line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003112
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003113 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003114 ptr += j;
3115 if (*ptr == '\n')
3116 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003117 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003118 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003119
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003120 skip_redisplay:
3121 kbinput = get_kbinput(edit, &meta_key);
3122 } while (kbinput != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003123
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003124#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003125 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003126#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003127
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003128 if (no_help_flag) {
Chris Allegretta70444892001-01-07 23:02:02 +00003129 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003130 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003131 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003132 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003133 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003134 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003135
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003136 curs_set(old_cursor);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003137 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003138
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003139 /* The help_init() at the beginning allocated help_text, which has
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003140 * now been written to the screen. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003141 free(help_text);
3142 help_text = NULL;
3143
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003144 return 1;
3145}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003146#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003147
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003148/* Highlight the current word being replaced or spell checked. We
3149 * expect word to have tabs and control characters expanded. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003150void do_replace_highlight(int highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003151{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003152 int y = xplustabs();
3153 size_t word_len = strlen(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003154
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003155 y = get_page_start(y) + COLS - y;
3156 /* Now y is the number of characters we can display on this
3157 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003158
3159 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003160
Chris Allegrettafb62f732000-12-05 11:36:41 +00003161 if (highlight_flag)
3162 wattron(edit, A_REVERSE);
3163
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003164#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003165 /* This is so we can show zero-length regexes. */
3166 if (word_len == 0)
3167 waddstr(edit, " ");
3168 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003169#endif
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003170 waddnstr(edit, word, y - 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003171
3172 if (word_len > y)
3173 waddch(edit, '$');
3174 else if (word_len == y)
3175 waddch(edit, word[word_len - 1]);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003176
3177 if (highlight_flag)
3178 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003179}
3180
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003181#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003182/* Dump the passed-in file structure to stderr. */
3183void dump_buffer(const filestruct *inptr)
3184{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003185 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003186 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003187 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003188 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003189 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003190 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003191
3192 while (inptr != NULL) {
3193 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
3194 inptr = inptr->next;
3195 }
3196}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003197
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003198/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00003199void dump_buffer_reverse(void)
3200{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003201 const filestruct *fileptr = filebot;
3202
3203 while (fileptr != NULL) {
3204 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
3205 fileptr = fileptr->prev;
3206 }
3207}
3208#endif /* DEBUG */
3209
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003210#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003211#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003212#define XLCREDIT_LEN 8
3213
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00003214/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003215void do_credits(void)
3216{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003217 int crpos = 0, xlpos = 0;
3218 const char *credits[CREDIT_LEN] = {
3219 NULL, /* "The nano text editor" */
3220 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003221 VERSION,
3222 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003223 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003224 "Chris Allegretta",
3225 "Jordi Mallach",
3226 "Adam Rogoyski",
3227 "Rob Siemborski",
3228 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003229 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003230 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00003231 "Ken Tyler",
3232 "Sven Guckes",
3233 "Florian König",
3234 "Pauli Virtanen",
3235 "Daniele Medri",
3236 "Clement Laforet",
3237 "Tedi Heriyanto",
3238 "Bill Soudan",
3239 "Christian Weisgerber",
3240 "Erik Andersen",
3241 "Big Gaute",
3242 "Joshua Jensen",
3243 "Ryan Krebs",
3244 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003245 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003246 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003247 "Plattsburgh State University",
3248 "Benet Laboratories",
3249 "Amy Allegretta",
3250 "Linda Young",
3251 "Jeremy Robichaud",
3252 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003253 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003254 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003255 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003256 "Thomas Dickey",
3257 "Pavel Curtis",
3258 "Zeyd Ben-Halim",
3259 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003260 NULL, /* "and anyone else we forgot..." */
3261 NULL, /* "Thank you for using nano!" */
3262 "",
3263 "",
3264 "",
3265 "",
David Lawrence Ramsey6481c3f2004-01-09 23:06:54 +00003266 "(c) 1999-2004 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003267 "",
3268 "",
3269 "",
3270 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003271 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003272 };
3273
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003274 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00003275 "The nano text editor",
3276 "version",
3277 "Brought to you by:",
3278 "Special thanks to:",
3279 "The Free Software Foundation",
3280 "For ncurses:",
3281 "and anyone else we forgot...",
3282 "Thank you for using nano!"
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003283 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003284
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003285 curs_set(0);
3286 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003287 scrollok(edit, TRUE);
3288 blank_titlebar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003289 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003290 blank_statusbar();
3291 blank_bottombars();
3292 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003293 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003294 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003295
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003296 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
3297 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003298 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003299 if (crpos < CREDIT_LEN) {
3300 const char *what = credits[crpos];
3301 size_t start_x;
3302
3303 if (what == NULL) {
3304 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00003305 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003306 xlpos++;
3307 }
3308 start_x = COLS / 2 - strlen(what) / 2 - 1;
3309 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x, what);
3310 }
3311 napms(700);
3312 scroll(edit);
3313 wrefresh(edit);
3314 if (wgetch(edit) != ERR)
3315 break;
3316 napms(700);
3317 scroll(edit);
3318 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003319 }
3320
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003321 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003322 nodelay(edit, FALSE);
3323 curs_set(1);
3324 display_main_list();
3325 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003326}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003327#endif