blob: eb8a961caa6d51d0184c2572b2d5f5fa817f9e47 [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 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000052 * Note: VT220 and VT320 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.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000088 *
89 * Note that Center (5) on the numeric keypad with NumLock off can also
90 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +000091
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000092#ifndef NANO_SMALL
93/* Reset all the input routines that rely on character sequences. */
94void reset_kbinput(void)
95{
96 get_translated_kbinput(0, NULL, TRUE);
97 get_ascii_kbinput(0, 0, TRUE);
98 get_untranslated_kbinput(0, 0, FALSE, TRUE);
99}
100#endif
101
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000102/* Read in a single input character. If it's ignored, swallow it and go
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000103 * on. Otherwise, try to translate it from ASCII, extended keypad
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000104 * values, and/or escape sequences. Set meta_key to TRUE when we get a
105 * meta sequence. Supported extended keypad values consist of [arrow
106 * key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace, the
107 * editing keypad (Insert, Delete, Home, End, PageUp, and PageDown), the
108 * function keypad (F1-F14), and the numeric keypad with NumLock off.
109 * Assume nodelay(win) is FALSE. */
David Lawrence Ramsey1576d532004-03-19 21:46:34 +0000110int get_kbinput(WINDOW *win, int *meta_key)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000111{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000112 int kbinput, es, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000113
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000114#ifndef NANO_SMALL
115 allow_pending_sigwinch(TRUE);
116#endif
117
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000118 *meta_key = FALSE;
119
120 while (retval == ERR) {
121 /* Read a character using blocking input, since using
122 * non-blocking input will eat up all unused CPU. Then pass it
123 * to get_translated_kbinput(). Continue until we get a
124 * complete sequence. */
125 kbinput = wgetch(win);
126 retval = get_translated_kbinput(kbinput, &es
127#ifndef NANO_SMALL
128 , FALSE
129#endif
130 );
131
132 /* If we got an escape sequence, read it in, including the
133 * initial non-escape, as verbatim input. */
134 if (es) {
135 int *escape_seq = NULL;
136 size_t es_len;
137
138 /* First, assume that we got a meta sequence. Set meta_key
139 * to TRUE and save the character we got as the result. We
David Lawrence Ramsey4e1a98c2004-06-15 01:48:51 +0000140 * do this so that if the keyboard buffer is full when we
141 * send back the character we got below (in which case we'll
142 * lose that character), it'll still be properly interpreted
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000143 * as a meta sequence. */
144 *meta_key = TRUE;
145 retval = tolower(kbinput);
146
147 /* Next, send back the character we got and read in the
148 * complete escape sequence. */
149 ungetch(kbinput);
150 escape_seq = get_verbatim_kbinput(win, escape_seq, &es_len,
151 FALSE);
152
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000153 /* If the escape sequence is more than one character
154 * long, set meta_key to FALSE, translate the escape
155 * sequence into the corresponding key value, and save
156 * that as the result. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000157 if (es_len > 1) {
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000158 int ignore_seq;
159
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000160 *meta_key = FALSE;
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000161 retval = get_escape_seq_kbinput(escape_seq, es_len,
162 &ignore_seq);
163
164 if (retval == ERR && !ignore_seq) {
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000165 /* This escape sequence is unrecognized. Send it
166 * back. */
167 for (; es_len > 1; es_len--)
168 ungetch(escape_seq[es_len - 1]);
169 retval = escape_seq[0];
170 }
171 }
172 free(escape_seq);
173 }
174 }
175
176#ifdef DEBUG
177 fprintf(stderr, "get_kbinput(): kbinput = %d, meta_key = %d\n", kbinput, *meta_key);
178#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000179
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000180#ifndef NANO_SMALL
181 allow_pending_sigwinch(FALSE);
182#endif
183
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000184 return retval;
185}
186
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000187/* Translate acceptable ASCII, extended keypad values, and escape
188 * sequences into their corresponding key values. Set es to TRUE when
189 * we get an escape sequence. Assume nodelay(win) is FALSE. */
190int get_translated_kbinput(int kbinput, int *es
191#ifndef NANO_SMALL
192 , int reset
193#endif
194 )
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000195{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +0000196 static int escapes = 0;
197 static size_t ascii_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000198 int retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000199
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000200#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000201 if (reset) {
202 escapes = 0;
203 ascii_digits = 0;
204 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000205 }
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000206#endif
207
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000208 *es = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000209
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000210 switch (kbinput) {
211 case ERR:
212 break;
213 case NANO_CONTROL_3:
214 /* Increment the escape counter. */
215 escapes++;
216 switch (escapes) {
217 case 1:
218 /* One escape: wait for more input. */
219 case 2:
220 /* Two escapes: wait for more input. */
221 break;
222 default:
223 /* More than two escapes: reset the escape counter
224 * and wait for more input. */
225 escapes = 0;
226 }
227 break;
228#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
229 /* Since we don't change the default SIGWINCH handler when
230 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
231 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
232 case KEY_RESIZE:
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000233 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000234#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000235#ifdef PDCURSES
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000236 case KEY_SHIFT_L:
237 case KEY_SHIFT_R:
238 case KEY_CONTROL_L:
239 case KEY_CONTROL_R:
240 case KEY_ALT_L:
241 case KEY_ALT_R:
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000242 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000243#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000244 default:
245 switch (escapes) {
246 case 0:
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000247 switch (kbinput) {
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000248 case NANO_CONTROL_8:
249 retval = ISSET(REBIND_DELETE) ?
250 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000251 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000252 case KEY_DOWN:
253 retval = NANO_NEXTLINE_KEY;
254 break;
255 case KEY_UP:
256 retval = NANO_PREVLINE_KEY;
257 break;
258 case KEY_LEFT:
259 retval = NANO_BACK_KEY;
260 break;
261 case KEY_RIGHT:
262 retval = NANO_FORWARD_KEY;
263 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000264#ifdef KEY_HOME
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000265 /* HP-UX 10 and 11 don't support KEY_HOME. */
266 case KEY_HOME:
267 retval = NANO_HOME_KEY;
268 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000269#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000270 case KEY_BACKSPACE:
271 retval = NANO_BACKSPACE_KEY;
272 break;
273 case KEY_DC:
274 retval = ISSET(REBIND_DELETE) ?
275 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
276 break;
277 case KEY_IC:
278 retval = NANO_INSERTFILE_KEY;
279 break;
280 case KEY_NPAGE:
281 retval = NANO_NEXTPAGE_KEY;
282 break;
283 case KEY_PPAGE:
284 retval = NANO_PREVPAGE_KEY;
285 break;
286 case KEY_ENTER:
287 retval = NANO_ENTER_KEY;
288 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000289 case KEY_A1: /* Home (7) on numeric keypad
290 * with NumLock off. */
291 retval = NANO_HOME_KEY;
292 break;
293 case KEY_A3: /* PageUp (9) on numeric keypad
294 * with NumLock off. */
295 retval = NANO_PREVPAGE_KEY;
296 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000297 case KEY_B2: /* Center (5) on numeric keypad
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000298 * with NumLock off. */
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000299 break;
300 case KEY_C1: /* End (1) on numeric keypad
301 * with NumLock off. */
302 retval = NANO_END_KEY;
303 break;
304 case KEY_C3: /* PageDown (4) on numeric
305 * keypad with NumLock off. */
306 retval = NANO_NEXTPAGE_KEY;
307 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000308#ifdef KEY_BEG
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000309 /* Slang doesn't support KEY_BEG. */
310 case KEY_BEG: /* Center (5) on numeric keypad
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000311 * with NumLock off. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000312 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000313#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000314#ifdef KEY_END
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000315 /* HP-UX 10 and 11 don't support KEY_END. */
316 case KEY_END:
317 retval = NANO_END_KEY;
318 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000319#endif
320#ifdef KEY_SUSPEND
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000321 /* Slang doesn't support KEY_SUSPEND. */
322 case KEY_SUSPEND:
323 retval = NANO_SUSPEND_KEY;
324 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000325#endif
326#ifdef KEY_SLEFT
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000327 /* Slang doesn't support KEY_SLEFT. */
328 case KEY_SLEFT:
329 retval = NANO_BACK_KEY;
330 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000331#endif
332#ifdef KEY_SRIGHT
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000333 /* Slang doesn't support KEY_SRIGHT. */
334 case KEY_SRIGHT:
335 retval = NANO_FORWARD_KEY;
336 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000337#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000338 default:
339 retval = kbinput;
340 break;
341 }
342 break;
343 case 1:
344 /* One escape followed by a non-escape: escape
345 * sequence mode. Reset the escape counter and set
346 * es to TRUE. */
347 escapes = 0;
348 *es = TRUE;
349 break;
350 case 2:
351 switch (kbinput) {
352 case '0':
353 case '1':
354 case '2':
355 case '3':
356 case '4':
357 case '5':
358 case '6':
359 case '7':
360 case '8':
361 case '9':
362 /* Two escapes followed by one or more
363 * digits: ASCII character sequence mode.
364 * If the digit sequence's range is limited
365 * to 2XX (the first digit is in the '0' to
366 * '2' range and it's the first digit, or if
367 * it's in the full digit range and it's not
368 * the first digit), increment the ASCII
369 * digit counter and interpret the digit.
370 * If the digit sequence's range is not
371 * limited to 2XX, fall through. */
372 if (kbinput <= '2' || ascii_digits > 0) {
373 ascii_digits++;
374 kbinput = get_ascii_kbinput(kbinput,
375 ascii_digits
376#ifndef NANO_SMALL
377 , FALSE
378#endif
379 );
380
381 if (kbinput != ERR) {
382 /* If we've read in a complete ASCII
383 * digit sequence, reset the ASCII
384 * digit counter and the escape
385 * counter and save the corresponding
386 * ASCII character as the result. */
387 ascii_digits = 0;
388 escapes = 0;
389 retval = kbinput;
390 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000391 }
David Lawrence Ramsey3b0729c2004-06-12 02:10:07 +0000392 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000393 default:
394 /* Reset the escape counter. */
395 escapes = 0;
396 if (ascii_digits == 0)
397 /* Two escapes followed by a non-digit
398 * or a digit that would create an ASCII
399 * digit sequence greater than 2XX, and
400 * we're not in the middle of an ASCII
401 * character sequence: control character
402 * sequence mode. Interpret the control
403 * sequence and save the corresponding
404 * control character as the result. */
405 retval = get_control_kbinput(kbinput);
406 else {
407 /* If we were in the middle of an ASCII
408 * character sequence, reset the ASCII
409 * digit counter and save the character
410 * we got as the result. */
411 ascii_digits = 0;
412 retval = kbinput;
413 }
414 }
415 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000416 }
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +0000417
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000418#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +0000419 fprintf(stderr, "get_translated_kbinput(): kbinput = %d, es = %d, escapes = %d, ascii_digits = %lu, retval = %d\n", kbinput, *es, escapes, (unsigned long)ascii_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000420#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000421
422 /* Return the result. */
423 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000424}
425
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000426/* Translate an ASCII character sequence: turn a three-digit decimal
427 * ASCII code from 000-255 into its corresponding ASCII character. */
428int get_ascii_kbinput(int kbinput, size_t ascii_digits
429#ifndef NANO_SMALL
430 , int reset
431#endif
432 )
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000433{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000434 static int ascii_kbinput = 0;
435 int retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000436
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000437#ifndef NANO_SMALL
438 if (reset) {
439 ascii_kbinput = 0;
440 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000441 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000442#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000443
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000444 switch (ascii_digits) {
445 case 1:
446 /* Read in the first of the three ASCII digits. */
447 switch (kbinput) {
448 /* Add the digit we got to the 100's position of the
449 * ASCII character sequence holder. */
450 case '0':
451 case '1':
452 case '2':
453 ascii_kbinput += (kbinput - '0') * 100;
454 break;
455 default:
456 retval = kbinput;
457 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000458 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000459 case 2:
460 /* Read in the second of the three ASCII digits. */
461 switch (kbinput) {
462 /* Add the digit we got to the 10's position of the
463 * ASCII character sequence holder. */
464 case '0':
465 case '1':
466 case '2':
467 case '3':
468 case '4':
469 case '5':
470 ascii_kbinput += (kbinput - '0') * 10;
471 break;
472 case '6':
473 case '7':
474 case '8':
475 case '9':
476 if (ascii_kbinput < 200) {
477 ascii_kbinput += (kbinput - '0') * 10;
478 break;
479 }
480 default:
481 retval = kbinput;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000482 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000483 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000484 case 3:
485 /* Read in the third of the three ASCII digits. */
486 switch (kbinput) {
487 /* Add the digit we got to the 1's position of the ASCII
488 * character sequence holder, and save the corresponding
489 * ASCII character as the result. */
490 case '0':
491 case '1':
492 case '2':
493 case '3':
494 case '4':
495 case '5':
496 ascii_kbinput += (kbinput - '0');
497 retval = ascii_kbinput;
498 break;
499 case '6':
500 case '7':
501 case '8':
502 case '9':
503 if (ascii_kbinput < 250) {
504 ascii_kbinput += (kbinput - '0');
505 retval = ascii_kbinput;
506 break;
507 }
508 default:
509 retval = kbinput;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000510 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000511 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000512 }
513
514#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +0000515 fprintf(stderr, "get_ascii_kbinput(): kbinput = %d, ascii_digits = %lu, ascii_kbinput = %d, retval = %d\n", kbinput, (unsigned long)ascii_digits, ascii_kbinput, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000516#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000517
518 /* If the result is an ASCII character, reset the ASCII character
519 * sequence holder. */
520 if (retval != ERR)
521 ascii_kbinput = 0;
522
523 return retval;
524}
525
526/* Translate a control character sequence: turn an ASCII non-control
527 * character into its corresponding control character. */
528int get_control_kbinput(int kbinput)
529{
530 int retval = ERR;
531
532 /* We don't handle Ctrl-2 here, since Esc Esc 2 could be the first
533 * part of an ASCII character sequence. */
534
535 /* Ctrl-2 (Ctrl-Space) == Ctrl-@ == Ctrl-` */
536 if (kbinput == ' ' || kbinput == '@' || kbinput == '`')
537 retval = NANO_CONTROL_SPACE;
538 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
539 else if (kbinput >= '3' && kbinput <= '7')
540 retval = kbinput - 24;
541 /* Ctrl-8 (Ctrl-?) */
542 else if (kbinput == '8' || kbinput == '?')
543 retval = NANO_CONTROL_8;
544 /* Ctrl-A to Ctrl-_ */
545 else if (kbinput >= 'A' && kbinput <= '_')
546 retval = kbinput - 64;
547 /* Ctrl-a to Ctrl-~ */
548 else if (kbinput >= 'a' && kbinput <= '~')
549 retval = kbinput - 96;
550 else
551 retval = kbinput;
552
553#ifdef DEBUG
David Lawrence Ramseycff55582004-06-30 12:28:15 +0000554 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000555#endif
556
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000557 return retval;
558}
559
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000560/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000561 * keypad values, nto their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000562 * are generated when the keypad doesn't support the needed keys. If
563 * the escape sequence is recognized but we want to ignore it, return
564 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
565 * set ignore_seq to FALSE. Assume that Escape has already been read
566 * in. */
567int get_escape_seq_kbinput(int *escape_seq, size_t es_len, int
568 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000569{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000570 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000571
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000572 *ignore_seq = FALSE;
573
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000574 if (es_len > 1) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000575 switch (escape_seq[0]) {
576 case 'O':
577 switch (escape_seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000578 case '2':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000579 if (es_len >= 3) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000580 switch (escape_seq[2]) {
581 case 'P': /* Esc O 2 P == F13 on
582 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000583 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000584 break;
585 case 'Q': /* Esc O 2 Q == F14 on
586 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000587 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000588 break;
589 }
590 }
591 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000592 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
593 case 'B': /* Esc O B == Down on
594 * VT100/VT320/xterm. */
595 case 'C': /* Esc O C == Right on
596 * VT100/VT320/xterm. */
597 case 'D': /* Esc O D == Left on
598 * VT100/VT320/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000599 retval = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000600 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000601 case 'E': /* Esc O E == Center (5) on numeric keypad
602 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000603 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000604 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000605 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000606 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000607 break;
608 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000609 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000610 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000611 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000612 * NumLock off on VT100/VT220/VT320/xterm/
613 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000614 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000615 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000616 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Hurd
617 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000618 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000619 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000620 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Hurd
621 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000622 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000623 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000624 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Hurd
625 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000626 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000627 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000628 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Hurd
629 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000630 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000631 break;
632 case 'T': /* Esc O T == F5 on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000633 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000634 break;
635 case 'U': /* Esc O U == F6 on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000636 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000637 break;
638 case 'V': /* Esc O V == F7 on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000639 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000640 break;
641 case 'W': /* Esc O W == F8 on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000642 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000643 break;
644 case 'X': /* Esc O X == F9 on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000645 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000646 break;
647 case 'Y': /* Esc O Y == F10 on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000648 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000649 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000650 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000651 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000652 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000653 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000654 retval = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000655 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000656 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000657 * NumLock off on VT100/VT220/VT320/xterm/
658 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000659 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000660 break;
661 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000662 * NumLock off on VT100/VT220/VT320/xterm/
663 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000664 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000665 break;
666 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000667 * NumLock off on VT100/VT220/VT320/xterm/
668 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000669 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000670 break;
671 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000672 * NumLock off on VT100/VT220/VT320/xterm/
673 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000674 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000675 break;
676 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000677 * with NumLock off on VT100/VT220/VT320/
678 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000679 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000680 break;
681 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000682 * NumLock off on VT100/VT220/VT320/xterm/
683 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000684 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000685 break;
686 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000687 * with NumLock off on VT100/VT220/VT320/
688 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000689 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000690 break;
691 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000692 * with NumLock off on VT100/VT220/VT320/
693 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000694 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000695 break;
696 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000697 * with NumLock off on VT100/VT220/VT320/
698 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000699 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000700 break;
701 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000702 * keypad with NumLock off on VT100/VT220/
703 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000704 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000705 break;
706 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000707 * with NumLock off on VT100/VT220/VT320/
708 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000709 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000710 break;
711 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000712 * with NumLock off on VT100/VT220/VT320/
713 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000714 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000715 break;
716 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000717 * with NumLock off on VT100/VT220/VT320/
718 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000719 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000720 break;
721 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000722 * with NumLock off on VT100/VT220/VT320/
723 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000724 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000725 break;
726 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000727 * with NumLock off on VT100/VT220/VT320/
728 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000729 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000730 break;
731 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000732 * with NumLock off on VT100/VT220/VT320/
733 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000734 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000735 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000736 }
737 break;
738 case 'o':
739 switch (escape_seq[1]) {
740 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000741 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000742 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000743 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000744 retval = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000745 break;
746 }
747 break;
748 case '[':
749 switch (escape_seq[1]) {
750 case '1':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000751 if (es_len >= 3) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000752 switch (escape_seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000753 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
754 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000755 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000756 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000757 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
758 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000759 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000760 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000761 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
762 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000763 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000764 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000765 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
766 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000767 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000768 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000769 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
770 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000771 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000772 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000773 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000774 * VT220/VT320/Linux console/
775 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000776 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000777 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000778 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000779 * VT220/VT320/Linux console/
780 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000781 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000782 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000783 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000784 * VT220/VT320/Linux console/
785 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000786 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000787 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000788 case ';':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000789 if (es_len >= 4) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000790 switch (escape_seq[3]) {
791 case '2':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000792 if (es_len >= 5) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000793 switch (escape_seq[4]) {
794 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
795 * xterm. */
796 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
797 * xterm. */
798 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
799 * xterm. */
800 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
801 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000802 retval = get_escape_seq_abcd(escape_seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000803 break;
804 }
805 }
806 break;
807 case '5':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000808 if (es_len >= 5) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000809 switch (escape_seq[4]) {
810 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
811 * xterm. */
812 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
813 * xterm. */
814 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
815 * xterm. */
816 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
817 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000818 retval = get_escape_seq_abcd(escape_seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000819 break;
820 }
821 }
822 break;
823 }
824 }
825 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000826 default: /* Esc [ 1 ~ == Home on
827 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000828 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000829 break;
830 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000831 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000832 break;
833 case '2':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000834 if (es_len >= 3) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000835 switch (escape_seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000836 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000837 * VT220/VT320/Linux console/
838 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000839 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000840 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000841 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000842 * VT220/VT320/Linux console/
843 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000844 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000845 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000846 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000847 * VT220/VT320/Linux console/
848 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000849 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000850 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000851 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000852 * VT220/VT320/Linux console/
853 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000854 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000855 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000856 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000857 * VT220/VT320/Linux console/
858 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000859 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000860 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000861 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000862 * VT220/VT320/Linux console/
863 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000864 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000865 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000866 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000867 * VT220/VT320/Linux console/
868 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000869 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000870 break;
871 }
872 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000873 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000874 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
875 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000876 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000877 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000878 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000879 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000880 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000881 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000882 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
883 * Linux console/xterm; Esc [ 5 ^ ==
884 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000885 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000886 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000887 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
888 * Linux console/xterm; Esc [ 6 ^ ==
889 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000890 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000891 break;
892 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000893 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000894 break;
895 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000896 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000897 break;
898 case '9': /* Esc [ 9 == Delete on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000899 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000900 break;
901 case '@': /* Esc [ @ == Insert on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000902 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000903 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000904 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000905 * console/FreeBSD console/Hurd console/
906 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000907 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000908 * console/FreeBSD console/Hurd console/
909 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000910 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000911 * console/FreeBSD console/Hurd console/
912 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000913 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000914 * console/FreeBSD console/Hurd console/
915 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000916 retval = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000917 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000918 case 'E': /* Esc [ E == Center (5) on numeric keypad
919 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000920 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000921 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000922 case 'F': /* Esc [ F == End on FreeBSD
923 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000924 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000925 break;
926 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000927 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000928 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000929 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000930 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000931 * console/Hurd console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000932 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000933 break;
934 case 'I': /* Esc [ I == PageUp on FreeBSD
935 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000936 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000937 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000938 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000939 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000940 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000941 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000942 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000943 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000944 break;
945 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000946 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000947 break;
948 case 'O':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000949 if (es_len >= 3) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000950 switch (escape_seq[2]) {
951 case 'P': /* Esc [ O P == F1 on
952 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000953 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000954 break;
955 case 'Q': /* Esc [ O Q == F2 on
956 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000957 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000958 break;
959 case 'R': /* Esc [ O R == F3 on
960 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000961 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000962 break;
963 case 'S': /* Esc [ O S == F4 on
964 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000965 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000966 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000967 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000968 } else {
969 /* Esc [ O == F3 on FreeBSD console. */
970 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000971 }
972 break;
973 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000974 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000975 break;
976 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000977 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000978 break;
979 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000980 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000981 break;
982 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000983 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000984 break;
985 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000986 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000987 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000988 case 'U': /* Esc [ U == PageDown on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000989 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000990 break;
991 case 'V': /* Esc [ V == PageUp on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000992 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000993 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000994 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000995 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000996 break;
997 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000998 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000999 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001000 case 'Y': /* Esc [ Y == End on Hurd console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001001 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001002 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001003 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001004 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001005 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001006 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001007 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001008 case 'c': /* Esc [ c == Shift-Right on rxvt/
1009 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001010 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001011 retval = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001012 break;
1013 case '[':
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001014 if (es_len >= 3) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001015 switch (escape_seq[2]) {
1016 case 'A': /* Esc [ [ A == F1 on Linux
1017 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001018 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001019 break;
1020 case 'B': /* Esc [ [ B == F2 on Linux
1021 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001022 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001023 break;
1024 case 'C': /* Esc [ [ C == F3 on Linux
1025 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001026 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001027 break;
1028 case 'D': /* Esc [ [ D == F4 on Linux
1029 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001030 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001031 break;
1032 case 'E': /* Esc [ [ E == F5 on Linux
1033 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001034 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001035 break;
1036 }
1037 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001038 break;
1039 }
1040 break;
1041 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001042 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001043
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001044#ifdef DEBUG
David Lawrence Ramseye65e6392004-06-04 18:18:17 +00001045 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, *ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001046#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001047
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001048 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001049}
1050
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001051/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001052 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001053 * to many escape sequences. */
1054int get_escape_seq_abcd(int kbinput)
1055{
1056 switch (tolower(kbinput)) {
1057 case 'a':
1058 return NANO_PREVLINE_KEY;
1059 case 'b':
1060 return NANO_NEXTLINE_KEY;
1061 case 'c':
1062 return NANO_FORWARD_KEY;
1063 case 'd':
1064 return NANO_BACK_KEY;
1065 default:
1066 return ERR;
1067 }
1068}
1069
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001070/* Read in a string of input characters (e.g. an escape sequence)
1071 * verbatim. Store the string in v_kbinput and return the length
1072 * of the string in v_len. Assume nodelay(win) is FALSE. */
David Lawrence Ramseyf7080372004-07-08 17:15:10 +00001073int *get_verbatim_kbinput(WINDOW *win, int *v_kbinput, size_t *v_len,
1074 int allow_ascii)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001075{
1076 int kbinput;
1077 size_t i = 0, v_newlen = 0;
1078
1079#ifndef NANO_SMALL
1080 allow_pending_sigwinch(TRUE);
1081#endif
1082
1083 *v_len = 0;
1084 v_kbinput = (int *)nmalloc(sizeof(int));
1085
1086 /* Turn off flow control characters if necessary so that we can type
1087 * them in verbatim, and turn the keypad off so that we don't get
1088 * extended keypad values outside the ASCII range. */
1089 if (ISSET(PRESERVE))
1090 disable_flow_control();
1091 keypad(win, FALSE);
1092
1093 /* Read the first character using blocking input, since using
1094 * non-blocking input will eat up all unused CPU. Then increment
1095 * v_len and save the character in v_kbinput. */
1096 kbinput = wgetch(win);
1097 (*v_len)++;
1098 v_kbinput[0] = kbinput;
1099#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001100 fprintf(stderr, "get_verbatim_kbinput(): kbinput = %d, v_len = %lu\n", kbinput, (unsigned long)*v_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001101#endif
1102
1103 /* Read any following characters using non-blocking input, until
1104 * there aren't any left to be read, and save the complete string of
1105 * characters in v_kbinput, incrementing v_len accordingly. We read
1106 * them all at once in order to minimize the chance that there might
1107 * be a delay greater than nodelay() provides for between them, in
1108 * which case we'll stop before all of them are read. */
1109 nodelay(win, TRUE);
1110 while ((kbinput = wgetch(win)) != ERR) {
1111 (*v_len)++;
1112 v_kbinput = (int *)nrealloc(v_kbinput, *v_len * sizeof(int));
1113 v_kbinput[*v_len - 1] = kbinput;
1114#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001115 fprintf(stderr, "get_verbatim_kbinput(): kbinput = %d, v_len = %lu\n", kbinput, (unsigned long)*v_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001116#endif
1117 }
1118 nodelay(win, FALSE);
1119
1120 /* Pass the string of characters to get_untranslated_kbinput(), one
1121 * by one, so it can handle them as ASCII character sequences and/or
1122 * escape sequences. Filter out ERR's from v_kbinput in the
1123 * process; they shouldn't occur in the string of characters unless
1124 * we're reading an incomplete sequence, in which case we only want
1125 * to keep the complete sequence. */
1126 for (; i < *v_len; i++) {
1127 v_kbinput[v_newlen] = get_untranslated_kbinput(v_kbinput[i], i,
1128 allow_ascii
1129#ifndef NANO_SMALL
1130 , FALSE
1131#endif
1132 );
1133 if (v_kbinput[i] != ERR && v_kbinput[v_newlen] != ERR)
1134 v_newlen++;
1135 }
1136
1137 if (v_newlen == 0) {
1138 /* If there were no characters after the ERR's were filtered
1139 * out, set v_len and reallocate v_kbinput to account for
1140 * one character, and set that character to ERR. */
1141 *v_len = 1;
1142 v_kbinput = (int *)nrealloc(v_kbinput, sizeof(int));
1143 v_kbinput[0] = ERR;
1144 } else if (v_newlen != *v_len) {
1145 /* If there were fewer characters after the ERR's were filtered
1146 * out, set v_len and reallocate v_kbinput to account for
1147 * the new number of characters. */
1148 *v_len = v_newlen;
1149 v_kbinput = (int *)nrealloc(v_kbinput, *v_len * sizeof(int));
1150 }
1151
1152 /* If allow_ascii is TRUE and v_kbinput[0] is ERR, we need to
1153 * complete an ASCII character sequence. Keep reading in characters
1154 * using blocking input until we get a complete sequence. */
1155 if (allow_ascii && v_kbinput[0] == ERR) {
1156 while (v_kbinput[0] == ERR) {
1157 kbinput = wgetch(win);
1158 v_kbinput[0] = get_untranslated_kbinput(kbinput, i,
1159 allow_ascii
1160#ifndef NANO_SMALL
1161 , FALSE
1162#endif
1163 );
1164 i++;
1165 }
1166 }
1167
1168 /* Turn flow control characters back on if necessary and turn the
1169 * keypad back on now that we're done. */
1170 if (ISSET(PRESERVE))
1171 enable_flow_control();
1172 keypad(win, TRUE);
1173
1174#ifndef NANO_SMALL
1175 allow_pending_sigwinch(FALSE);
1176#endif
1177
1178 return v_kbinput;
1179}
1180
1181int get_untranslated_kbinput(int kbinput, size_t position, int
1182 allow_ascii
1183#ifndef NANO_SMALL
1184 , int reset
1185#endif
1186 )
1187{
1188 static size_t ascii_digits = 0;
1189 int retval;
1190
1191#ifndef NANO_SMALL
1192 if (reset) {
1193 ascii_digits = 0;
1194 return ERR;
1195 }
1196#endif
1197
1198 if (allow_ascii) {
1199 /* position is equal to the number of ASCII digits we've read so
1200 * far, and kbinput is a digit from '0' to '9': ASCII character
1201 * sequence mode. If the digit sequence's range is limited to
1202 * 2XX (the first digit is in the '0' to '2' range and it's the
1203 * first digit, or if it's in the full digit range and it's not
1204 * the first digit), increment the ASCII digit counter and
1205 * interpret the digit. If the digit sequence's range is not
1206 * limited to 2XX, fall through. */
1207 if (position == ascii_digits && kbinput >= '0' && kbinput <= '9') {
1208 if (kbinput <= '2' || ascii_digits > 0) {
1209 ascii_digits++;
1210 kbinput = get_ascii_kbinput(kbinput, ascii_digits
1211#ifndef NANO_SMALL
1212 , FALSE
1213#endif
1214 );
1215 if (kbinput != ERR)
1216 /* If we've read in a complete ASCII digit sequence,
1217 * reset the ASCII digit counter. */
1218 ascii_digits = 0;
1219 }
1220 } else if (ascii_digits > 0)
1221 /* position is not equal to the number of ASCII digits we've
1222 * read or kbinput is a non-digit, and we're in the middle
1223 * of an ASCII character sequence. Reset the ASCII digit
1224 * counter. */
1225 ascii_digits = 0;
1226 }
1227
1228 /* Save the corresponding ASCII character as the result if we've
1229 * read in a complete ASCII digit sequence, or the passed-in
1230 * character if we haven't. */
1231 retval = kbinput;
1232
1233#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001234 fprintf(stderr, "get_untranslated_kbinput(): kbinput = %d, position = %lu, ascii_digits = %lu\n", kbinput, (unsigned long)position, (unsigned long)ascii_digits);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001235#endif
1236
1237 return retval;
1238}
1239
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001240#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001241/* Check for a mouse event, and if one's taken place, save the
1242 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001243 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1244 * bottom two lines of the screen is visible and the mouse event took
1245 * place on it, figure out which shortcut was clicked and ungetch() the
1246 * equivalent keystroke(s). Return FALSE if no keystrokes were
1247 * ungetch()ed, or TRUE if at least one was. Assume that KEY_MOUSE has
1248 * already been read in. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001249int get_mouseinput(int *mouse_x, int *mouse_y, int allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001250{
1251 MEVENT mevent;
1252
1253 *mouse_x = -1;
1254 *mouse_y = -1;
1255
1256 /* First, get the actual mouse event. */
1257 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001258 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001259
1260 /* Save the screen coordinates where the mouse event took place. */
1261 *mouse_x = mevent.x;
1262 *mouse_y = mevent.y;
1263
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001264 /* If we're not allowing shortcuts' we're done now. */
1265 if (!allow_shortcuts)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001266 return FALSE;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001267
1268 /* Otherwise, if the current shortcut list is being displayed on the
1269 * last two lines of the screen and the mouse event took place
1270 * inside it, we need to figure out which shortcut was clicked and
1271 * ungetch() the equivalent keystroke(s) for it. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001272 if (!ISSET(NO_HELP) && wenclose(bottomwin, *mouse_y, *mouse_x)) {
1273 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001274 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001275 /* The number of shortcuts in the current shortcut list. */
1276 const shortcut *s = currshortcut;
1277 /* The actual shortcut we clicked on, starting at the first
1278 * one in the current shortcut list. */
1279
1280 /* Get the shortcut lists' length. */
1281 if (currshortcut == main_list)
1282 currslen = MAIN_VISIBLE;
1283 else
1284 currslen = length_of_list(currshortcut);
1285
1286 /* Calculate the width of each shortcut in the list (it's the
1287 * same for all of them). */
1288 if (currslen < 2)
1289 i = COLS / 6;
1290 else
1291 i = COLS / ((currslen / 2) + (currslen % 2));
1292
1293 /* Calculate the y-coordinates relative to the beginning of
1294 * bottomwin, i.e, the bottom three lines of the screen. */
1295 j = *mouse_y - (editwinrows + 3);
1296
1297 /* If we're on the statusbar, beyond the end of the shortcut
1298 * list, or beyond the end of a shortcut on the right side of
1299 * the screen, don't do anything. */
1300 if (j < 0 || (*mouse_x / i) >= currslen)
1301 return 0;
1302 j = (*mouse_x / i) * 2 + j;
1303 if (j >= currslen)
1304 return 0;
1305
1306 /* Go through the shortcut list to determine which shortcut was
1307 * clicked. */
1308 for (; j > 0; j--)
1309 s = s->next;
1310
David Lawrence Ramsey32613fa2004-05-24 18:40:41 +00001311 /* And ungetch() the equivalent control key. If it's a meta key
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001312 * sequence, we need to ungetch() Escape too. Assume that the
1313 * shortcut has an equivalent control key, meta key sequence, or
1314 * both. */
1315 if (s->ctrlval != NANO_NO_KEY)
1316 ungetch(s->ctrlval);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001317 else if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001318 ungetch(s->metaval);
1319 ungetch(NANO_CONTROL_3);
1320 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001321
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001322 return TRUE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001323 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001324 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001325}
1326#endif
1327
Chris Allegretta6df90f52002-07-19 01:08:59 +00001328/* Return the placewewant associated with current_x. That is, xplustabs
1329 * is the zero-based column position of the cursor. Value is no smaller
1330 * than current_x. */
1331size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001332{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001333 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001334}
1335
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001336/* actual_x() gives the index in str of the character displayed at
1337 * column xplus. That is, actual_x() is the largest value such that
1338 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
1339size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001340{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001341 size_t i = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001342 /* the position in str, returned */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001343 size_t length = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001344 /* the screen display width to str[i] */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001345
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001346 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001347
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001348 for (; length < xplus && *str != '\0'; i++, str++) {
1349 if (*str == '\t')
David Lawrence Ramsey0362c582003-09-30 03:31:56 +00001350 length += tabsize - (length % tabsize);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001351 else if (is_cntrl_char((int)*str))
Chris Allegretta6df90f52002-07-19 01:08:59 +00001352 length += 2;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001353 else
1354 length++;
1355 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001356 assert(length == strnlenpt(str - i, i));
1357 assert(i <= strlen(str - i));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001358
Chris Allegretta6df90f52002-07-19 01:08:59 +00001359 if (length > xplus)
1360 i--;
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001361
Chris Allegretta6df90f52002-07-19 01:08:59 +00001362 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00001363}
1364
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00001365/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001366 * columns wide are the first size characters of buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001367size_t strnlenpt(const char *buf, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00001368{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001369 size_t length = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001370
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001371 assert(buf != NULL);
1372 for (; *buf != '\0' && size != 0; size--, buf++) {
1373 if (*buf == '\t')
1374 length += tabsize - (length % tabsize);
1375 else if (is_cntrl_char((int)*buf))
1376 length += 2;
1377 else
1378 length++;
1379 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001380 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001381}
1382
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001383/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001384size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001385{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00001386 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001387}
1388
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001389void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001390{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001391 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001392}
1393
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001394void blank_edit(void)
1395{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001396 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001397 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001398 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001399}
1400
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001401void blank_statusbar(void)
1402{
1403 mvwaddstr(bottomwin, 0, 0, hblank);
1404}
1405
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001406void check_statblank(void)
1407{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001408 if (statblank > 1)
1409 statblank--;
1410 else if (statblank == 1 && !ISSET(CONSTUPDATE)) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001411 statblank = 0;
1412 blank_statusbar();
1413 wnoutrefresh(bottomwin);
1414 reset_cursor();
1415 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001416 }
1417}
1418
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001419void blank_bottombars(void)
1420{
1421 if (!ISSET(NO_HELP)) {
1422 mvwaddstr(bottomwin, 1, 0, hblank);
1423 mvwaddstr(bottomwin, 2, 0, hblank);
1424 }
1425}
1426
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001427/* Convert buf into a string that can be displayed on screen. The
1428 * caller wants to display buf starting with column start_col, and
1429 * extending for at most len columns. start_col is zero-based. len is
1430 * one-based, so len == 0 means you get "" returned. The returned
1431 * string is dynamically allocated, and should be freed. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001432char *display_string(const char *buf, size_t start_col, size_t len)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001433{
1434 size_t start_index;
1435 /* Index in buf of first character shown in return value. */
1436 size_t column;
1437 /* Screen column start_index corresponds to. */
1438 size_t end_index;
1439 /* Index in buf of last character shown in return value. */
1440 size_t alloc_len;
1441 /* The length of memory allocated for converted. */
1442 char *converted;
1443 /* The string we return. */
1444 size_t index;
1445 /* Current position in converted. */
1446
1447 if (len == 0)
1448 return mallocstrcpy(NULL, "");
1449
1450 start_index = actual_x(buf, start_col);
1451 column = strnlenpt(buf, start_index);
1452 assert(column <= start_col);
1453 end_index = actual_x(buf, start_col + len - 1);
1454 alloc_len = strnlenpt(buf, end_index + 1) - column;
1455 if (len > alloc_len + column - start_col)
1456 len = alloc_len + column - start_col;
1457 converted = charalloc(alloc_len + 1);
1458 buf += start_index;
1459 index = 0;
1460
1461 for (; index < alloc_len; buf++) {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001462 if (*buf == '\t') {
1463 converted[index++] =
1464#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
1465 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
1466#endif
1467 ' ';
1468 while ((column + index) % tabsize)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001469 converted[index++] = ' ';
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001470 } else if (is_cntrl_char(*buf)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001471 converted[index++] = '^';
1472 if (*buf == '\n')
1473 /* Treat newlines embedded in a line as encoded nulls;
1474 * the line in question should be run through unsunder()
1475 * before reaching here. */
1476 converted[index++] = '@';
1477 else if (*buf == NANO_CONTROL_8)
1478 converted[index++] = '?';
1479 else
1480 converted[index++] = *buf + 64;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001481 } else if (*buf == ' ')
1482 converted[index++] =
1483#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
1484 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
1485#endif
1486 ' ';
1487 else
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001488 converted[index++] = *buf;
1489 }
1490 assert(len <= alloc_len + column - start_col);
1491 charmove(converted, converted + start_col - column, len);
1492 null_at(&converted, len);
1493
1494 return charealloc(converted, len + 1);
1495}
1496
Chris Allegretta7662c862003-01-13 01:35:15 +00001497/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001498 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00001499 *
Chris Allegretta7662c862003-01-13 01:35:15 +00001500 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00001501 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001502void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001503{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001504 size_t x_real = strnlenpt(inputbuf, x);
1505 int wid = COLS - strlen(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00001506
Chris Allegretta6df90f52002-07-19 01:08:59 +00001507 assert(0 <= x && x <= strlen(inputbuf));
1508
Chris Allegrettab3655b42001-10-22 03:15:31 +00001509 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001510 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001511
Chris Allegretta6df90f52002-07-19 01:08:59 +00001512 mvwaddstr(bottomwin, 0, 0, buf);
1513 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001514
1515 if (COLS > 1)
1516 waddch(bottomwin, x_real < wid ? ' ' : '$');
1517 if (COLS > 2) {
1518 size_t page_start = x_real - x_real % wid;
1519 char *expanded = display_string(inputbuf, page_start, wid);
1520
1521 assert(wid > 0);
1522 assert(strlen(expanded) <= wid);
1523 waddstr(bottomwin, expanded);
1524 free(expanded);
1525 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
1526 } else
1527 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001528 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001529}
1530
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00001531/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00001532 * statusq(). */
Chris Allegrettaf717f982003-02-13 22:25:01 +00001533int nanogetstr(int allowtabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00001534#ifndef NANO_SMALL
1535 historyheadtype *history_list,
1536#endif
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001537 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00001538#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001539 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00001540#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00001541 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00001542{
1543 int kbinput;
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001544 int meta_key;
Chris Allegretta09fc4302003-01-16 22:16:38 +00001545 static int x = -1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001546 /* the cursor position in 'answer' */
1547 int xend;
1548 /* length of 'answer', the status bar text */
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001549 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001550 /* used by input_tab() */
1551 const shortcut *t;
Chris Allegretta598106e2002-01-19 01:59:37 +00001552
Chris Allegretta5beed502003-01-05 20:41:21 +00001553#ifndef NANO_SMALL
1554 /* for history */
1555 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00001556 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00001557 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001558 int last_kbinput = 0;
1559
1560 /* This variable is used in the search history code. use_cb == 0
1561 means that we're using the existing history and ignoring
1562 currentbuf. use_cb == 1 means that the entry in answer should be
1563 moved to currentbuf or restored from currentbuf to answer.
1564 use_cb == 2 means that the entry in currentbuf should be moved to
1565 answer or restored from answer to currentbuf. */
1566 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00001567#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001568 xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00001569
1570 /* Only put x at the end of the string if it's uninitialized or if
1571 it would be past the end of the string as it is. Otherwise,
1572 leave it alone. This is so the cursor position stays at the same
1573 place if a prompt-changing toggle is pressed. */
Chris Allegretta65f075d2003-02-13 03:03:49 +00001574 if (x == -1 || x > xend || resetstatuspos)
Chris Allegretta09fc4302003-01-16 22:16:38 +00001575 x = xend;
1576
Chris Allegrettae1e0fd62003-04-15 01:15:09 +00001577 answer = charealloc(answer, xend + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001578 if (xend > 0)
1579 strcpy(answer, def);
1580 else
1581 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001582
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00001583#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001584 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00001585#endif
1586
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001587 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00001588
Chris Allegretta6df90f52002-07-19 01:08:59 +00001589 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001590
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001591 /* Make sure any editor screen updates are displayed before getting
1592 input */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00001593 wnoutrefresh(edit);
1594 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00001595
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001596 /* If we're using restricted mode, we aren't allowed to change the
1597 * name of a file once it has one because that would allow writing
1598 * to files not specified on the command line. In this case,
1599 * disable all keys that would change the text if the filename isn't
1600 * blank and we're at the "Write File" prompt. */
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001601 while ((kbinput = get_kbinput(bottomwin, &meta_key)) != NANO_ENTER_KEY) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001602 for (t = s; t != NULL; t = t->next) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001603#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001604 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001605#endif
1606
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001607 /* Temporary hack to interpret NANO_HELP_FKEY correctly. */
1608 if (kbinput == t->funcval)
1609 kbinput = t->ctrlval;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00001610
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001611 if (kbinput == t->ctrlval && is_cntrl_char(kbinput)) {
Chris Allegretta5bf51d32000-11-16 06:01:10 +00001612
Chris Allegrettab3655b42001-10-22 03:15:31 +00001613#ifndef DISABLE_HELP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001614 /* Have to do this here, it would be too late to do it
1615 in statusq() */
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00001616 if (kbinput == NANO_HELP_KEY) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00001617 do_help();
1618 break;
1619 }
1620#endif
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001621#ifndef NANO_SMALL
1622 /* Have to handle these here too, for the time being */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001623 if (kbinput == NANO_PREVLINE_KEY || kbinput == NANO_NEXTLINE_KEY)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001624 break;
1625#endif
Chris Allegretta5af58892003-01-17 21:07:38 +00001626
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001627 return t->ctrlval;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001628 }
1629 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001630 assert(0 <= x && x <= xend && xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001631
Chris Allegretta04d848e2000-11-05 17:54:41 +00001632 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001633 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00001634
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001635 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00001636#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001637 case KEY_MOUSE:
1638 do_mouse();
1639 break;
1640#endif
Chris Allegretta658399a2001-06-14 02:54:22 +00001641 case NANO_HOME_KEY:
David Lawrence Ramseyc7acf692004-05-22 20:15:20 +00001642#ifndef NANO_SMALL
1643 if (ISSET(SMART_HOME)) {
1644 int old_x = x;
1645
1646 for (x = 0; isblank(answer[x]) && x < xend; x++)
1647 ;
1648
1649 if (x == old_x || x == xend)
1650 x = 0;
1651 } else
1652#endif
1653 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001654 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00001655 case NANO_END_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001656 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001657 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00001658 case NANO_FORWARD_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001659 if (x < xend)
1660 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001661 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001662 case NANO_DELETE_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001663 /* If we're using restricted mode, the filename isn't blank,
1664 * and we're at the "Write File" prompt, disable Delete. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001665 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1666 if (x < xend) {
1667 charmove(answer + x, answer + x + 1, xend - x);
1668 xend--;
1669 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001670 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001671 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001672 case NANO_CUT_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001673 /* If we're using restricted mode, the filename isn't blank,
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00001674 * and we're at the "Write File" prompt, disable Cut. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001675 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1676 null_at(&answer, 0);
1677 xend = 0;
1678 x = 0;
1679 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001680 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001681 case NANO_BACKSPACE_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001682 /* If we're using restricted mode, the filename isn't blank,
1683 * and we're at the "Write File" prompt, disable
1684 * Backspace. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001685 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1686 if (x > 0) {
1687 charmove(answer + x - 1, answer + x, xend - x + 1);
1688 x--;
1689 xend--;
1690 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001691 }
Chris Allegretta04d848e2000-11-05 17:54:41 +00001692 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001693 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001694#ifndef NANO_SMALL
1695 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00001696 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001697 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001698 history_list->current = (historytype *)history_list;
1699 history_list->len = strlen(answer);
1700 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001701
Chris Allegretta7662c862003-01-13 01:35:15 +00001702 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001703 complete = get_history_completion(history_list, answer);
1704 xend = strlen(complete);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001705 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00001706 answer = mallocstrcpy(answer, complete);
1707 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00001708 }
Chris Allegretta5beed502003-01-05 20:41:21 +00001709#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00001710 else
1711#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00001712#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00001713#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00001714 if (allowtabs) {
1715 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00001716
Chris Allegretta327abda2003-01-17 05:04:17 +00001717 answer = input_tab(answer, x, &tabbed, &shift, list);
1718 xend = strlen(answer);
1719 x += shift;
1720 if (x > xend)
1721 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00001722 }
1723#endif
1724 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00001725 case NANO_BACK_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001726 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001727 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001728 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001729 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001730#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00001731 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00001732
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001733 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
1734 isn't NULL, and currentbuf is different from answer,
1735 it means that we're scrolling up at the top of the
1736 search history, and we need to save the current
1737 answer in currentbuf; do this and reset use_cb to
1738 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00001739 if (currentbuf == NULL || (use_cb == 1 &&
1740 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00001741 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001742 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00001743 }
1744
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001745 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
1746 is different from answer, it means that we're
1747 scrolling up at the bottom of the search history, and
1748 we need to make the string in currentbuf the current
1749 answer; do this, blow away currentbuf since we don't
1750 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00001751 if (currentbuf != NULL && use_cb == 2 &&
1752 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001753 answer = mallocstrcpy(answer, currentbuf);
1754 free(currentbuf);
1755 currentbuf = NULL;
1756 xend = strlen(answer);
1757 use_cb = 0;
1758
1759 /* else get older search from the history list and save
1760 it in answer; if there is no older search, blank out
1761 answer */
1762 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001763 answer = mallocstrcpy(answer, history);
1764 xend = strlen(history);
1765 } else {
1766 answer = mallocstrcpy(answer, "");
1767 xend = 0;
1768 }
1769 x = xend;
1770 }
Chris Allegretta5beed502003-01-05 20:41:21 +00001771#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00001772 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001773 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001774#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00001775 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001776
1777 /* get newer search from the history list and save it
1778 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00001779 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001780 answer = mallocstrcpy(answer, history);
1781 xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00001782
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001783 /* if there is no newer search, we're here */
1784
1785 /* if currentbuf isn't NULL and use_cb isn't 2, it means
1786 that we're scrolling down at the bottom of the search
1787 history and we need to make the string in currentbuf
1788 the current answer; do this, blow away currentbuf
1789 since we don't need it anymore, and set use_cb to
1790 1 */
1791 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00001792 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00001793 free(currentbuf);
1794 currentbuf = NULL;
1795 xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001796 use_cb = 1;
1797
1798 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
1799 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00001800 the search history and the current answer (if it's
1801 not blank) needs to be saved in currentbuf; do this,
1802 blank out answer (if necessary), and set use_cb to
1803 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001804 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00001805 if (answer[0] != '\0') {
1806 currentbuf = mallocstrcpy(currentbuf, answer);
1807 answer = mallocstrcpy(answer, "");
1808 }
Chris Allegretta5beed502003-01-05 20:41:21 +00001809 xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001810 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00001811 }
1812 x = xend;
1813 }
1814#endif
1815 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00001816 default:
1817
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001818 for (t = s; t != NULL; t = t->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +00001819#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001820 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
Chris Allegretta598106e2002-01-19 01:59:37 +00001821 kbinput);
Chris Allegretta658399a2001-06-14 02:54:22 +00001822#endif
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001823 if (meta_key && (kbinput == t->metaval || kbinput == t->miscval))
David Lawrence Ramsey32613fa2004-05-24 18:40:41 +00001824 /* We hit a meta key. Do like above. We don't
David Lawrence Ramsey82138502003-12-24 08:03:54 +00001825 * just ungetch() the letter and let it get
1826 * caught above cause that screws the
1827 * keypad... */
1828 return kbinput;
Chris Allegretta658399a2001-06-14 02:54:22 +00001829 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001830
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001831 /* If we're using restricted mode, the filename isn't blank,
1832 * and we're at the "Write File" prompt, act as though the
1833 * unhandled character we got is a control character and
1834 * throw it away. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001835 if (is_cntrl_char(kbinput) || (ISSET(RESTRICTED) && filename[0] != '\0' && s == writefile_list))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001836 break;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001837 answer = charealloc(answer, xend + 2);
David Lawrence Ramsey9eff7462003-09-16 02:04:00 +00001838 charmove(answer + x + 1, answer + x, xend - x + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001839 xend++;
1840 answer[x] = kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001841 x++;
1842
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001843#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001844 fprintf(stderr, "input \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001845#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00001846 } /* switch (kbinput) */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00001847#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00001848 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00001849#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001850 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001851 wrefresh(bottomwin);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001852 } /* while (kbinput ...) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001853
Chris Allegretta5af58892003-01-17 21:07:38 +00001854 /* We finished putting in an answer; reset x */
1855 x = -1;
1856
Chris Allegretta7662c862003-01-13 01:35:15 +00001857 /* Just check for a blank answer here */
Chris Allegretta15c28f82003-01-05 21:47:06 +00001858 if (answer[0] == '\0')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001859 return -2;
1860 else
1861 return 0;
1862}
1863
Chris Allegrettaf717f982003-02-13 22:25:01 +00001864void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001865{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001866 size_t space;
1867 /* The space we have available for display. */
1868 size_t verlen = strlen(VERMSG) + 1;
1869 /* The length of the version message. */
1870 const char *prefix;
1871 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
1872 size_t prefixlen;
1873 /* strlen(prefix) + 1. */
1874 const char *state;
1875 /* "Modified", "View", or spaces the length of "Modified".
1876 * Tells the state of this buffer. */
1877 size_t statelen = 0;
1878 /* strlen(state) + 1. */
1879 char *exppath = NULL;
1880 /* The file name, expanded for display. */
1881 size_t explen = 0;
1882 /* strlen(exppath) + 1. */
1883 int newbuffer = FALSE;
1884 /* Do we say "New Buffer"? */
1885 int dots = FALSE;
1886 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001887
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001888 assert(path != NULL || filename != NULL);
1889 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001890
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001891 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001892
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001893 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001894
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001895 if (COLS <= 5 || COLS - 5 < verlen)
1896 space = 0;
1897 else {
1898 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00001899 /* Reserve 2/3 of the screen plus one column for after the
1900 * version message. */
1901 if (space < COLS - (COLS / 3) + 1)
1902 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001903 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001904
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001905 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00001906 /* The version message should only take up 1/3 of the screen
1907 * minus one column. */
1908 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001909 waddstr(topwin, " ");
1910 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001911
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001912 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001913 state = _("Modified");
1914 else if (path == NULL && ISSET(VIEW_MODE))
1915 state = _("View");
1916 else {
1917 if (space > 0)
1918 statelen = strnlen(_("Modified"), space - 1) + 1;
1919 state = &hblank[COLS - statelen];
1920 }
1921 statelen = strnlen(state, COLS);
1922 /* We need a space before state. */
1923 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
1924 statelen++;
1925
1926 assert(space >= 0);
1927 if (space == 0 || statelen >= space)
1928 goto the_end;
1929
1930#ifndef DISABLE_BROWSER
1931 if (path != NULL)
1932 prefix = _("DIR:");
1933 else
1934#endif
1935 if (filename[0] == '\0') {
1936 prefix = _("New Buffer");
1937 newbuffer = TRUE;
1938 } else
1939 prefix = _("File:");
1940 assert(statelen < space);
1941 prefixlen = strnlen(prefix, space - statelen);
1942 /* If newbuffer is FALSE, we need a space after prefix. */
1943 if (!newbuffer && prefixlen + statelen < space)
1944 prefixlen++;
1945
1946 if (path == NULL)
1947 path = filename;
David Lawrence Ramsey1dcf36a2004-05-23 21:17:56 +00001948 space -= prefixlen + statelen;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001949 /* space is now the room we have for the file name. */
1950 if (!newbuffer) {
1951 size_t lenpt = strlenpt(path), start_col;
1952
1953 if (lenpt > space)
1954 start_col = actual_x(path, lenpt - space);
1955 else
1956 start_col = 0;
1957 exppath = display_string(path, start_col, space);
1958 dots = (lenpt > space);
1959 explen = strlen(exppath);
1960 }
1961
1962 if (!dots) {
1963 /* There is room for the whole filename, so we center it. */
1964 waddnstr(topwin, hblank, (space - explen) / 3);
1965 waddnstr(topwin, prefix, prefixlen);
1966 if (!newbuffer) {
1967 assert(strlen(prefix) + 1 == prefixlen);
1968 waddch(topwin, ' ');
1969 waddstr(topwin, exppath);
1970 }
1971 } else {
1972 /* We will say something like "File: ...ename". */
1973 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramsey1dcf36a2004-05-23 21:17:56 +00001974 if (space <= 0 || newbuffer)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001975 goto the_end;
1976 waddch(topwin, ' ');
1977 waddnstr(topwin, "...", space);
1978 if (space <= 3)
1979 goto the_end;
1980 space -= 3;
1981 assert(explen = space + 3);
1982 waddnstr(topwin, exppath + 3, space);
1983 }
1984
1985 the_end:
1986
1987 free(exppath);
1988
1989 if (COLS <= 1 || statelen >= COLS - 1)
1990 mvwaddnstr(topwin, 0, 0, state, COLS);
1991 else {
1992 assert(COLS - statelen - 2 >= 0);
1993 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
1994 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
1995 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00001996
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001997 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001998
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001999 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002000 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002001 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002002}
2003
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002004/* If modified is not already set, set it and update titlebar. */
2005void set_modified(void)
2006{
2007 if (!ISSET(MODIFIED)) {
2008 SET(MODIFIED);
2009 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002010 }
2011}
2012
2013void statusbar(const char *msg, ...)
2014{
2015 va_list ap;
2016
2017 va_start(ap, msg);
2018
2019 /* Curses mode is turned off. If we use wmove() now, it will muck
2020 * up the terminal settings. So we just use vfprintf(). */
2021 if (curses_ended) {
2022 vfprintf(stderr, msg, ap);
2023 va_end(ap);
2024 return;
2025 }
2026
2027 /* Blank out the line. */
2028 blank_statusbar();
2029
2030 if (COLS >= 4) {
2031 char *bar;
2032 char *foo;
2033 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002034#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2035 int old_whitespace = ISSET(WHITESPACE_DISPLAY);
2036 UNSET(WHITESPACE_DISPLAY);
2037#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002038 bar = charalloc(COLS - 3);
2039 vsnprintf(bar, COLS - 3, msg, ap);
2040 va_end(ap);
2041 foo = display_string(bar, 0, COLS - 4);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002042#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2043 if (old_whitespace)
2044 SET(WHITESPACE_DISPLAY);
2045#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002046 free(bar);
2047 foo_len = strlen(foo);
2048 start_x = (COLS - foo_len - 4) / 2;
2049
2050 wmove(bottomwin, 0, start_x);
2051 wattron(bottomwin, A_REVERSE);
2052
2053 waddstr(bottomwin, "[ ");
2054 waddstr(bottomwin, foo);
2055 free(foo);
2056 waddstr(bottomwin, " ]");
2057 wattroff(bottomwin, A_REVERSE);
2058 wnoutrefresh(bottomwin);
2059 reset_cursor();
2060 wrefresh(edit);
2061 /* Leave the cursor at its position in the edit window, not
2062 * in the statusbar. */
2063 }
2064
2065 SET(DISABLE_CURPOS);
2066 statblank = 26;
2067}
2068
Chris Allegretta6232d662002-05-12 19:52:15 +00002069void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002070{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002071 size_t i, colwidth, slen;
2072 char *keystr;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002073
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002074 if (ISSET(NO_HELP))
2075 return;
2076
Chris Allegretta6232d662002-05-12 19:52:15 +00002077 if (s == main_list) {
2078 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002079 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002080 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002081 slen = length_of_list(s);
2082
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002083 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002084 if (slen > MAIN_VISIBLE)
2085 slen = MAIN_VISIBLE;
2086 }
2087
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002088 /* There will be this many characters per column. We need at least
2089 * 3 to display anything properly.*/
2090 colwidth = COLS / ((slen / 2) + (slen % 2));
2091 keystr = charalloc(colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002092
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002093 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002094
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002095 for (i = 0; i < slen; i++, s = s->next) {
2096 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
Chris Allegretta658399a2001-06-14 02:54:22 +00002097
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002098 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002099#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002100 if (s->ctrlval == NANO_HISTORY_KEY)
2101 strncpy(keystr, _("Up"), colwidth);
2102 else
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002103#endif
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002104 if (s->ctrlval == NANO_CONTROL_SPACE)
2105 strncpy(keystr, "^ ", colwidth);
2106 else if (s->ctrlval == NANO_CONTROL_8)
2107 strncpy(keystr, "^?", colwidth);
2108 /* Normal values. Assume that the shortcut has an equivalent
2109 * control key, meta key sequence, or both. */
2110 else if (s->ctrlval != NANO_NO_KEY)
2111 snprintf(keystr, colwidth, "^%c", s->ctrlval + 64);
2112 else if (s->metaval != NANO_NO_KEY)
2113 snprintf(keystr, colwidth, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00002114
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002115 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002116 }
2117
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002118 free(keystr);
2119
2120 wnoutrefresh(bottomwin);
2121 reset_cursor();
2122 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002123}
2124
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002125/* Write a shortcut key to the help area at the bottom of the window.
2126 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2127 * to write at most len characters, even if len is very small and
2128 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2129 * the whole string! We do not bother padding the entry with blanks. */
2130void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002131{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002132 assert(keystroke != NULL && desc != NULL && len >= 0);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002133 wattron(bottomwin, A_REVERSE);
2134 waddnstr(bottomwin, keystroke, len);
2135 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002136 len -= strlen(keystroke) + 1;
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002137 if (len > 0) {
2138 waddch(bottomwin, ' ');
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002139 waddnstr(bottomwin, desc, len);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002140 }
2141}
2142
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002143/* And so start the display update routines. */
2144
2145#ifndef NDEBUG
2146int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002147{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002148 int check_line = 0;
2149 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002150
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002151 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
2152 check_line++;
2153 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002154}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002155#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00002156
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002157/* nano scrolls horizontally within a line in chunks. This function
2158 * returns the column number of the first character displayed in the
2159 * window when the cursor is at the given column. Note that
2160 * 0 <= column - get_page_start(column) < COLS. */
2161size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002162{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002163 assert(COLS > 0);
2164 if (column == 0 || column < COLS - 1)
2165 return 0;
2166 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002167 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002168 else if (COLS > 2)
2169 return column - (COLS - 2);
2170 else
2171 return column - (COLS - 1);
2172 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002173}
2174
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002175/* Resets current_y, based on the position of current, and puts the
2176 * cursor at (current_y, current_x). */
2177void reset_cursor(void)
2178{
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002179 /* Yuck. This condition can be true after open_file() when opening
2180 * the first file. */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002181 if (edittop == NULL)
2182 return;
2183
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002184 current_y = current->lineno - edittop->lineno;
2185 if (current_y < editwinrows) {
2186 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002187 wmove(edit, current_y, x - get_page_start(x));
2188 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002189}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002190
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002191/* edit_add() takes care of the job of actually painting a line into the
2192 * edit window. fileptr is the line to be painted, at row yval of the
2193 * window. converted is the actual string to be written to the window,
2194 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00002195 * characters. start is the column number of the first character of
2196 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002197 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002198void edit_add(const filestruct *fileptr, const char *converted, int
2199 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002200{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002201#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
2202 size_t startpos = actual_x(fileptr->data, start);
2203 /* The position in fileptr->data of the leftmost character
2204 * that displays at least partially on the window. */
2205 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2206 /* The position in fileptr->data of the first character that is
2207 * completely off the window to the right.
2208 *
2209 * Note that endpos might be beyond the null terminator of the
2210 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002211#endif
2212
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002213 assert(fileptr != NULL && converted != NULL);
2214 assert(strlen(converted) <= COLS);
2215
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002216 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002217 * just the text that needs it). */
2218 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002219
Chris Allegretta7dd77682001-12-08 19:52:28 +00002220#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00002221 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002222 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002223
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002224 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2225 int x_start;
2226 /* Starting column for mvwaddnstr. Zero-based. */
2227 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002228 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002229 * characters on a whole line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002230 regmatch_t startmatch; /* match position for start_regexp */
2231 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002232
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002233 if (tmpcolor->bright)
2234 wattron(edit, A_BOLD);
2235 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002236 /* Two notes about regexec(). Return value 0 means there is
2237 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002238 * after the match. */
2239
2240 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002241 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002242 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002243
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002244 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002245 * last match. Even though two matches may overlap, we
2246 * want to ignore them, so that we can highlight
2247 * C-strings correctly. */
2248 while (k < endpos) {
2249 /* Note the fifth parameter to regexec(). It says
2250 * not to match the beginning-of-line character
2251 * unless k is 0. If regexec() returns REG_NOMATCH,
2252 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00002253 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002254 &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002255 break;
2256 /* Translate the match to the beginning of the line. */
2257 startmatch.rm_so += k;
2258 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002259 if (startmatch.rm_so == startmatch.rm_eo) {
2260 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00002261 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002262 } else if (startmatch.rm_so < endpos &&
2263 startmatch.rm_eo > startpos) {
2264 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002265 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002266 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002267 x_start = strnlenpt(fileptr->data,
2268 startmatch.rm_so) - start;
2269 paintlen = strnlenpt(fileptr->data,
2270 startmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002271 if (paintlen > COLS - x_start)
2272 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002273
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002274 assert(0 <= x_start && 0 < paintlen &&
2275 x_start + paintlen <= COLS);
2276 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002277 converted + x_start, paintlen);
2278 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002279 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002280 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002281 } else {
2282 /* This is a multi-line regexp. There are two steps.
2283 * First, we have to see if the beginning of the line is
2284 * colored by a start on an earlier line, and an end on
2285 * this line or later.
2286 *
2287 * We find the first line before fileptr matching the
2288 * start. If every match on that line is followed by an
2289 * end, then go to step two. Otherwise, find the next line
2290 * after start_line matching the end. If that line is not
2291 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002292
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002293 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002294 /* the first line before fileptr matching start */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002295 regoff_t start_col;
2296 /* where it starts in that line */
2297 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002298
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002299 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00002300 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002301 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002302 /* If there is an end on this line, there is no need
2303 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002304 if (regexec(tmpcolor->end, start_line->data, 0,
2305 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002306 goto step_two;
2307 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002308 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002309 /* No start found, so skip to the next step. */
2310 if (start_line == NULL)
2311 goto step_two;
2312 /* Now start_line is the first line before fileptr
2313 * containing a start match. Is there a start on this
2314 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002315
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002316 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002317 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002318 start_col += startmatch.rm_so;
2319 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002320 if (regexec(tmpcolor->end,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002321 start_line->data + start_col + startmatch.rm_eo,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002322 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
2323 REG_NOTBOL) == REG_NOMATCH)
2324 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002325 break;
2326 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002327 if (regexec(&tmpcolor->start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002328 start_line->data + start_col, 1,
2329 &startmatch, REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002330 /* No later start on this line. */
2331 goto step_two;
2332 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002333 /* Indeed, there is a start not followed on this line by
2334 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002335
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002336 /* We have already checked that there is no end before
2337 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002338 * the start at all? We don't paint unterminated
2339 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002340 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002341 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00002342 regexec(tmpcolor->end, end_line->data, 1,
2343 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002344 end_line = end_line->next;
2345
2346 /* No end found, or it is too early. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002347 if (end_line == NULL ||
2348 (end_line == fileptr && endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002349 goto step_two;
2350
2351 /* Now paint the start of fileptr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002352 paintlen = end_line != fileptr ? COLS :
2353 strnlenpt(fileptr->data, endmatch.rm_eo) - start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002354 if (paintlen > COLS)
2355 paintlen = COLS;
2356
2357 assert(0 < paintlen && paintlen <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002358 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002359
2360 /* We have already painted the whole line. */
2361 if (paintlen == COLS)
2362 goto skip_step_two;
2363
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002364 step_two:
2365 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002366 start_col = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002367 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002368 if (regexec(&tmpcolor->start,
2369 fileptr->data + start_col, 1, &startmatch,
2370 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
2371 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002372 /* No more starts on this line. */
2373 break;
2374 /* Translate the match to be relative to the
2375 * beginning of the line. */
2376 startmatch.rm_so += start_col;
2377 startmatch.rm_eo += start_col;
2378
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002379 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002380 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002381 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002382 x_start = strnlenpt(fileptr->data,
2383 startmatch.rm_so) - start;
2384 if (regexec(tmpcolor->end,
2385 fileptr->data + startmatch.rm_eo, 1, &endmatch,
2386 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002387 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002388 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002389 endmatch.rm_so += startmatch.rm_eo;
2390 endmatch.rm_eo += startmatch.rm_eo;
2391 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002392 * appear on this page, and is the match more
2393 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002394 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002395 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002396 paintlen = strnlenpt(fileptr->data,
2397 endmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002398 if (x_start + paintlen > COLS)
2399 paintlen = COLS - x_start;
2400
2401 assert(0 <= x_start && 0 < paintlen &&
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002402 x_start + paintlen <= COLS);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002403 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002404 converted + x_start, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002405 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002406 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002407 /* There is no end on this line. But we haven't
2408 * yet looked for one on later lines. */
2409 end_line = fileptr->next;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002410 while (end_line != NULL &&
2411 regexec(tmpcolor->end, end_line->data, 0,
2412 NULL, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002413 end_line = end_line->next;
2414 if (end_line != NULL) {
2415 assert(0 <= x_start && x_start < COLS);
2416 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002417 converted + x_start, COLS - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002418 /* We painted to the end of the line, so
2419 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002420 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002421 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002422 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002423 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002424 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002425 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002426
Chris Allegrettace452fb2003-02-03 02:56:44 +00002427 skip_step_two:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002428 wattroff(edit, A_BOLD);
2429 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
2430 } /* for tmpcolor in colorstrings */
2431 }
Chris Allegretta598106e2002-01-19 01:59:37 +00002432#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002433
Chris Allegretta7dd77682001-12-08 19:52:28 +00002434#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002435 if (ISSET(MARK_ISSET)
2436 && (fileptr->lineno <= mark_beginbuf->lineno
2437 || fileptr->lineno <= current->lineno)
2438 && (fileptr->lineno >= mark_beginbuf->lineno
2439 || fileptr->lineno >= current->lineno)) {
2440 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002441
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002442 const filestruct *top;
2443 /* Either current or mark_beginbuf, whichever is first. */
2444 size_t top_x;
2445 /* current_x or mark_beginx, corresponding to top. */
2446 const filestruct *bot;
2447 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002448 int x_start;
2449 /* Starting column for mvwaddnstr. Zero-based. */
2450 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002451 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002452 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002453
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002454 mark_order(&top, &top_x, &bot, &bot_x);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002455
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002456 if (top->lineno < fileptr->lineno || top_x < startpos)
2457 top_x = startpos;
2458 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2459 bot_x = endpos;
2460
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002461 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002462 if (top_x < endpos && bot_x > startpos) {
2463 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002464
2465 /* x_start is the expanded location of the beginning of the
2466 * mark minus the beginning of the page. */
2467 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002468
2469 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002470 /* If the end of the mark is off the page, paintlen is
2471 * -1, meaning that everything on the line gets
2472 * painted. */
2473 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002474 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002475 /* Otherwise, paintlen is the expanded location of the
2476 * end of the mark minus the expanded location of the
2477 * beginning of the mark. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002478 paintlen = strnlenpt(fileptr->data, bot_x)
2479 - (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002480
2481 /* If x_start is before the beginning of the page, shift
2482 * paintlen x_start characters to compensate, and put
2483 * x_start at the beginning of the page. */
2484 if (x_start < 0) {
2485 paintlen += x_start;
2486 x_start = 0;
2487 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002488
2489 assert(x_start >= 0 && x_start <= strlen(converted));
2490
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002491 wattron(edit, A_REVERSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002492 mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002493 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002494 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002495 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002496#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002497}
2498
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002499/* Just update one line in the edit buffer. Basically a wrapper for
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002500 * edit_add().
2501 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002502 * If fileptr != current, then index is considered 0. The line will be
2503 * displayed starting with fileptr->data[index]. Likely args are
2504 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002505void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002506{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002507 int line;
2508 /* line in the edit window for CURSES calls */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002509 char *converted;
2510 /* fileptr->data converted to have tabs and control characters
2511 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002512 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002513
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002514 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002515
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002516 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002517
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002518 /* We assume the line numbers are valid. Is that really true? */
2519 assert(line < 0 || line == check_linenumbers(fileptr));
2520
2521 if (line < 0 || line >= editwinrows)
2522 return;
2523
2524 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002525 mvwaddstr(edit, line, 0, hblank);
2526
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002527 /* Next, convert variables that index the line to their equivalent
2528 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002529 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002530 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002531
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002532 /* Expand the line, replacing Tab by spaces, and control characters
2533 * by their display form. */
2534 converted = display_string(fileptr->data, page_start, COLS);
Robert Siemborski53875912000-06-16 04:25:30 +00002535
Chris Allegretta4dc03d52002-05-11 03:04:44 +00002536 /* Now, paint the line */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002537 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002538 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002539
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002540 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002541 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002542 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002543 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002544}
2545
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002546/* Return a nonzero value if we need an update after moving
2547 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002548 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002549int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002550{
2551 return
2552#ifndef NANO_SMALL
2553 ISSET(MARK_ISSET) ||
2554#endif
2555 get_page_start(old_pww) != get_page_start(placewewant);
2556}
2557
2558/* Return a nonzero value if we need an update after moving vertically.
2559 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002560 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002561int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002562{
2563 return
2564#ifndef NANO_SMALL
2565 ISSET(MARK_ISSET) ||
2566#endif
2567 get_page_start(old_pww) != get_page_start(placewewant);
2568}
2569
2570/* Scroll the edit window in the given direction and the given number
2571 * of lines, and draw new lines on the blank lines left after the
2572 * scrolling. direction is the direction to scroll, either UP or DOWN,
2573 * and nlines is the number of lines to scroll. Don't redraw the old
2574 * topmost or bottommost line (where we assume current is) before
2575 * scrolling or draw the new topmost or bottommost line after scrolling
2576 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002577 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002578void edit_scroll(updown direction, int nlines)
2579{
2580 filestruct *foo;
2581 int i, scroll_rows = 0;
2582
2583 /* Scrolling less than one line or more than editwinrows lines is
2584 * redundant, so don't allow it. */
2585 if (nlines < 1 || nlines > editwinrows)
2586 return;
2587
2588 /* Move the top line of the edit window up or down (depending on the
2589 * value of direction) nlines lines. If there are fewer lines of
2590 * text than that left, move it to the top or bottom line of the
2591 * file (depending on the value of direction). Keep track of
2592 * how many lines we moved in scroll_rows. */
2593 for (i = nlines; i > 0; i--) {
2594 if (direction == UP) {
2595 if (edittop->prev == NULL)
2596 break;
2597 edittop = edittop->prev;
2598 scroll_rows--;
2599 } else {
2600 if (edittop->next == NULL)
2601 break;
2602 edittop = edittop->next;
2603 scroll_rows++;
2604 }
2605 }
2606
2607 /* Scroll the text on the screen up or down scroll_rows lines,
2608 * depending on the value of direction. */
2609 scrollok(edit, TRUE);
2610 wscrl(edit, scroll_rows);
2611 scrollok(edit, FALSE);
2612
2613 foo = edittop;
2614 if (direction != UP) {
2615 int slines = editwinrows - nlines;
2616 for (; slines > 0 && foo != NULL; slines--)
2617 foo = foo->next;
2618 }
2619
2620 /* And draw new lines on the blank top or bottom lines of the edit
2621 * window, depending on the value of direction. Don't draw the new
2622 * topmost or new bottommost line. */
2623 while (scroll_rows != 0 && foo != NULL) {
2624 if (foo->next != NULL)
2625 update_line(foo, 0);
2626 if (direction == UP)
2627 scroll_rows++;
2628 else
2629 scroll_rows--;
2630 foo = foo->next;
2631 }
2632}
2633
2634/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002635 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002636void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002637{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00002638 int do_refresh = need_vertical_update(0) ||
2639 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002640 const filestruct *foo;
2641
2642 /* If either old_current or current is offscreen, refresh the screen
2643 * and get out. */
2644 if (old_current->lineno < edittop->lineno || old_current->lineno >=
2645 edittop->lineno + editwinrows || current->lineno <
2646 edittop->lineno || current->lineno >= edittop->lineno +
2647 editwinrows) {
2648 edit_refresh();
2649 return;
2650 }
2651
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00002652 /* Update old_current and current if we're not on the first page
2653 * and/or we're not on the same page as before. If the mark is on,
2654 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002655 foo = old_current;
2656 while (foo != current) {
2657 if (do_refresh)
2658 update_line(foo, 0);
2659#ifndef NANO_SMALL
2660 if (!ISSET(MARK_ISSET))
2661#endif
2662 break;
2663 if (foo->lineno > current->lineno)
2664 foo = foo->prev;
2665 else
2666 foo = foo->next;
2667 }
2668 if (do_refresh)
2669 update_line(current, current_x);
2670}
2671
Chris Allegretta6df90f52002-07-19 01:08:59 +00002672/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002673void edit_refresh(void)
2674{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002675 /* Neither of these conditions should occur, but they do. edittop
2676 * is NULL when you open an existing file on the command line, and
Chris Allegretta6df90f52002-07-19 01:08:59 +00002677 * ENABLE_COLOR is defined. Yuck. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002678 if (current == NULL)
2679 return;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002680 if (edittop == NULL)
2681 edittop = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002682
Chris Allegretta63d0b482003-01-26 19:47:10 +00002683 if (current->lineno < edittop->lineno ||
2684 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002685 /* Note that edit_update() changes edittop so that
2686 * current->lineno = edittop->lineno + editwinrows / 2. Thus
2687 * when it then calls edit_refresh(), there is no danger of
2688 * getting an infinite loop. */
Chris Allegrettada721be2000-07-31 01:26:42 +00002689 edit_update(current, CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002690 else {
2691 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002692 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002693
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002694#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002695 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002696#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002697
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002698 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00002699 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002700 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002701 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002702 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002703 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002704 }
2705 while (nlines < editwinrows) {
2706 mvwaddstr(edit, nlines, 0, hblank);
2707 nlines++;
2708 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002709 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002710 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002711 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002712}
2713
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002714/* Nice generic routine to update the edit buffer, given a pointer to the
2715 * file struct =) */
David Lawrence Ramsey1356a0a2003-09-10 20:31:02 +00002716void edit_update(filestruct *fileptr, topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002717{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002718 if (fileptr == NULL)
2719 return;
2720
Chris Allegretta6df90f52002-07-19 01:08:59 +00002721 if (location != TOP) {
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002722 int goal = (location == NONE) ? current_y : editwinrows / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002723
David Lawrence Ramseyd91ab6e2003-09-07 23:57:24 +00002724 for (; goal > 0 && fileptr->prev != NULL; goal--)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002725 fileptr = fileptr->prev;
2726 }
2727 edittop = fileptr;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002728 edit_refresh();
2729}
2730
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002731/* Ask a question on the statusbar. Answer will be stored in answer
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002732 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
Chris Allegretta88520c92001-05-05 17:45:54 +00002733 * otherwise, the valid shortcut key caught. Def is any editable text we
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002734 * want to put up by default.
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002735 *
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002736 * New arg tabs tells whether or not to allow tab completion. */
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002737int statusq(int allowtabs, const shortcut *s, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002738#ifndef NANO_SMALL
2739 historyheadtype *which_history,
2740#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00002741 const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002742{
2743 va_list ap;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002744 char *foo = charalloc(COLS - 3);
Chris Allegretta9caa1932002-02-15 20:08:05 +00002745 int ret;
Chris Allegretta2084acc2001-11-29 03:43:08 +00002746#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002747 bool list = FALSE;
Chris Allegretta2084acc2001-11-29 03:43:08 +00002748#endif
2749
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002750 bottombars(s);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002751
2752 va_start(ap, msg);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002753 vsnprintf(foo, COLS - 4, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002754 va_end(ap);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002755 foo[COLS - 4] = '\0';
Chris Allegretta8ce24132001-04-30 11:28:46 +00002756
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002757 ret = nanogetstr(allowtabs, foo, def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002758#ifndef NANO_SMALL
2759 which_history,
Chris Allegretta2084acc2001-11-29 03:43:08 +00002760#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002761 s
2762#ifndef DISABLE_TABCOMP
2763 , &list
2764#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002765 );
Chris Allegretta6df90f52002-07-19 01:08:59 +00002766 free(foo);
Chris Allegretta65f075d2003-02-13 03:03:49 +00002767 resetstatuspos = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002768
2769 switch (ret) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002770 case NANO_FIRSTLINE_KEY:
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002771 case NANO_FIRSTLINE_FKEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002772 do_first_line();
Chris Allegretta65f075d2003-02-13 03:03:49 +00002773 resetstatuspos = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002774 break;
2775 case NANO_LASTLINE_KEY:
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002776 case NANO_LASTLINE_FKEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002777 do_last_line();
Chris Allegretta65f075d2003-02-13 03:03:49 +00002778 resetstatuspos = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002779 break;
David Lawrence Ramsey8faf3052003-09-04 20:25:29 +00002780#ifndef DISABLE_JUSTIFY
2781 case NANO_PARABEGIN_KEY:
2782 do_para_begin();
2783 resetstatuspos = 1;
2784 break;
2785 case NANO_PARAEND_KEY:
2786 do_para_end();
2787 resetstatuspos = 1;
2788 break;
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002789 case NANO_FULLJUSTIFY_KEY:
David Lawrence Ramseyd12fd4b2004-05-28 15:05:56 +00002790 if (!ISSET(VIEW_MODE))
2791 do_full_justify();
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002792 resetstatuspos = 1;
2793 break;
David Lawrence Ramsey8faf3052003-09-04 20:25:29 +00002794#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002795 case NANO_CANCEL_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00002796 ret = -1;
Chris Allegretta65f075d2003-02-13 03:03:49 +00002797 resetstatuspos = 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002798 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002799 }
Chris Allegrettaa90d0cf2003-02-10 02:55:03 +00002800 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002801
2802#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002803 fprintf(stderr, "I got \"%s\"\n", answer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002804#endif
2805
Chris Allegretta6df90f52002-07-19 01:08:59 +00002806#ifndef DISABLE_TABCOMP
2807 /* if we've done tab completion, there might be a list of
2808 filename matches on the edit window at this point; make sure
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002809 they're cleared off. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002810 if (list)
2811 edit_refresh();
2812#endif
2813
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002814 return ret;
2815}
2816
David Lawrence Ramsey52453442004-06-26 15:24:16 +00002817/* Ask a simple yes/no question, specified in msg, on the statusbar.
2818 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
2819 * and -1 for abort (^C). */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002820int do_yesno(int all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002821{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002822 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00002823 const char *yesstr; /* String of yes characters accepted. */
2824 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002825 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00002826
David Lawrence Ramsey52453442004-06-26 15:24:16 +00002827 /* yesstr, nostr, and allstr are strings of any length. Each string
2828 * consists of all characters accepted as a valid character for that
2829 * value. The first value will be the one displayed in the
2830 * shortcuts. Translators: if possible, specify both the shortcuts
2831 * for your language and English. For example, in French: "OoYy"
2832 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002833 yesstr = _("Yy");
2834 nostr = _("Nn");
2835 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002836
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002837 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002838 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00002839
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002840 if (COLS < 32)
2841 width = COLS / 2;
2842
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002843 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00002844 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002845
Chris Allegretta6232d662002-05-12 19:52:15 +00002846 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00002847 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002848 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002849
2850 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002851 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00002852 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002853 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002854 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002855
Chris Allegrettadb28e962003-01-28 01:23:40 +00002856 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00002857 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002858 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002859
Chris Allegrettadb28e962003-01-28 01:23:40 +00002860 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002861 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002862 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00002863
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002864 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002865
2866 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002867 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002868
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002869 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002870
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002871 wrefresh(bottomwin);
2872
Chris Allegrettadb28e962003-01-28 01:23:40 +00002873 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002874 int kbinput;
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00002875 int meta_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00002876#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002877 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00002878#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002879
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00002880 kbinput = get_kbinput(edit, &meta_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002881
2882 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00002883 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00002884#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002885 /* Look ma! We get to duplicate lots of code from
2886 * do_mouse()!! */
2887 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00002888 kbinput = get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002889
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002890 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
2891 wenclose(bottomwin, mouse_y, mouse_x) && mouse_x <
2892 (width * 2) && mouse_y >= editwinrows + 3) {
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002893
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002894 int x = mouse_x / width;
2895 /* Did we click in the first column of shortcuts, or
2896 * the second? */
2897 int y = mouse_y - editwinrows - 3;
2898 /* Did we click in the first row of shortcuts? */
2899
2900 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
2901
2902 /* x = 0 means they clicked Yes or No.
2903 * y = 0 means Yes or All. */
2904 ok = -2 * x * y + x - y + 1;
2905
2906 if (ok == 2 && !all)
2907 ok = -2;
2908 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002909 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00002910#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002911 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00002912 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00002913 else if (strchr(yesstr, kbinput) != NULL)
2914 ok = 1;
2915 else if (strchr(nostr, kbinput) != NULL)
2916 ok = 0;
2917 else if (all && strchr(allstr, kbinput) != NULL)
2918 ok = 2;
2919 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002920
Chris Allegrettadb28e962003-01-28 01:23:40 +00002921 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002922}
2923
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00002924void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002925{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002926 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002927 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002928 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002929 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002930 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002931 wnoutrefresh(bottomwin);
2932 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002933 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002934 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002935 clearok(bottomwin, FALSE);
2936 edit_refresh();
2937 titlebar(NULL);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002938}
2939
2940void display_main_list(void)
2941{
2942 bottombars(main_list);
2943}
2944
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00002945/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
2946 * display the cursor position. Otherwise, we display it only if the
2947 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00002948 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002949 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
2950 * old_i and old_totsize. That way, we leave the current statusbar
2951 * alone, but next time we will display. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00002952void do_cursorpos(int constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002953{
Chris Allegrettad26ab912003-01-28 01:16:47 +00002954 const filestruct *fileptr;
2955 unsigned long i = 0;
2956 static unsigned long old_i = 0;
2957 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002958
Chris Allegrettad26ab912003-01-28 01:16:47 +00002959 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00002960
2961 if (old_totsize == -1)
2962 old_totsize = totsize;
2963
Chris Allegrettad26ab912003-01-28 01:16:47 +00002964 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
2965 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00002966 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00002967 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00002968 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00002969
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002970 /* Check whether totsize is correct. Else there is a bug
2971 * somewhere. */
2972 assert(current != filebot || i == totsize);
2973
Chris Allegrettad26ab912003-01-28 01:16:47 +00002974 if (constant && ISSET(DISABLE_CURPOS)) {
2975 UNSET(DISABLE_CURPOS);
2976 old_i = i;
2977 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00002978 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00002979 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00002980
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00002981 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002982 * unconditionally; otherwise, only display the position when the
2983 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00002984 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002985 size_t xpt = xplustabs() + 1;
2986 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00002987 int linepct = 100 * current->lineno / totlines;
2988 int colpct = 100 * xpt / cur_len;
2989 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
2990
2991 statusbar(
2992 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
2993 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002994 (unsigned long)xpt, (unsigned long)cur_len, colpct,
Chris Allegrettad26ab912003-01-28 01:16:47 +00002995 i, totsize, bytepct);
2996 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00002997 }
2998
2999 old_i = i;
3000 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003001}
3002
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003003void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003004{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003005 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003006}
3007
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003008#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003009/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003010int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003011{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003012 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003013
3014 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3015 ptr++;
3016 j++;
3017 }
3018 if (j == COLS - 5) {
3019 /* Don't wrap at the first of two spaces following a period. */
3020 if (*ptr == ' ' && *(ptr + 1) == ' ')
3021 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003022 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003023 while (*ptr != ' ' && j > 0) {
3024 ptr--;
3025 j--;
3026 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003027 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003028 if (j == 0)
3029 j = COLS - 5;
3030 }
3031 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
3032 return j;
3033}
3034
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003035/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003036void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003037{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003038 int line = 0;
3039 /* The line number in help_text of the first displayed help line.
3040 * This variable is zero-based. */
3041 int no_more = 0;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003042 /* no_more means the end of the help text is shown, so don't go
3043 * down any more. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003044 int kbinput = ERR, meta_key;
3045
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003046 int old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003047#ifndef DISABLE_MOUSE
3048 const shortcut *oldshortcut = currshortcut;
3049 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003050 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003051#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003052
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003053 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003054 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003055 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003056 blank_statusbar();
3057
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003058 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003059 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003060 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003061
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003062#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003063 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003064 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003065 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003066#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003067
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003068 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003069 /* Make sure that the help screen's shortcut list will actually
3070 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003071 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003072 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003073 }
3074 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003075
3076 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003077 int i;
3078 int old_line = line;
3079 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003080 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003081
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003082 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003083#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003084 case KEY_MOUSE:
3085 do_mouse();
3086 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003087#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003088 case NANO_NEXTPAGE_KEY:
3089 case NANO_NEXTPAGE_FKEY:
3090 if (!no_more)
3091 line += editwinrows - 2;
3092 break;
3093 case NANO_PREVPAGE_KEY:
3094 case NANO_PREVPAGE_FKEY:
3095 if (line > 0) {
3096 line -= editwinrows - 2;
3097 if (line < 0)
3098 line = 0;
3099 }
3100 break;
3101 case NANO_PREVLINE_KEY:
3102 if (line > 0)
3103 line--;
3104 break;
3105 case NANO_NEXTLINE_KEY:
3106 if (!no_more)
3107 line++;
3108 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003109 }
3110
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003111 if (line == old_line && kbinput != ERR)
3112 goto skip_redisplay;
3113
3114 blank_edit();
3115
3116 assert(COLS > 5);
3117
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003118 /* Calculate where in the text we should be, based on the
3119 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003120 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003121 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003122 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003123 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003124 }
3125
Chris Allegretta4640fe32003-02-10 03:10:03 +00003126 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003127 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003128
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003129 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003130 ptr += j;
3131 if (*ptr == '\n')
3132 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003133 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003134 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003135
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003136 skip_redisplay:
3137 kbinput = get_kbinput(edit, &meta_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003138 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3139 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003140
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003141#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003142 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003143#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003144
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003145 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003146 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003147 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003148 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003149 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003150 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003151 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003152
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003153 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003154 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003155
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003156 /* The help_init() at the beginning allocated help_text. Since
3157 * help_text has now been written to the screen, we don't need it
3158 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003159 free(help_text);
3160 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003161}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003162#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003163
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003164/* Highlight the current word being replaced or spell checked. We
3165 * expect word to have tabs and control characters expanded. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003166void do_replace_highlight(int highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003167{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003168 size_t y = xplustabs();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003169 size_t word_len = strlen(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003170
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003171 y = get_page_start(y) + COLS - y;
3172 /* Now y is the number of characters we can display on this
3173 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003174
3175 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003176
Chris Allegrettafb62f732000-12-05 11:36:41 +00003177 if (highlight_flag)
3178 wattron(edit, A_REVERSE);
3179
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003180#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003181 /* This is so we can show zero-length regexes. */
3182 if (word_len == 0)
3183 waddstr(edit, " ");
3184 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003185#endif
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003186 waddnstr(edit, word, y - 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003187
3188 if (word_len > y)
3189 waddch(edit, '$');
3190 else if (word_len == y)
3191 waddch(edit, word[word_len - 1]);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003192
3193 if (highlight_flag)
3194 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003195}
3196
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003197#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003198/* Dump the passed-in file structure to stderr. */
3199void dump_buffer(const filestruct *inptr)
3200{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003201 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003202 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003203 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003204 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003205 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003206 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003207
3208 while (inptr != NULL) {
3209 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
3210 inptr = inptr->next;
3211 }
3212}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003213
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003214/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00003215void dump_buffer_reverse(void)
3216{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003217 const filestruct *fileptr = filebot;
3218
3219 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00003220 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003221 fileptr = fileptr->prev;
3222 }
3223}
3224#endif /* DEBUG */
3225
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003226#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003227#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003228#define XLCREDIT_LEN 8
3229
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00003230/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003231void do_credits(void)
3232{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003233 int crpos = 0, xlpos = 0;
3234 const char *credits[CREDIT_LEN] = {
3235 NULL, /* "The nano text editor" */
3236 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003237 VERSION,
3238 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003239 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003240 "Chris Allegretta",
3241 "Jordi Mallach",
3242 "Adam Rogoyski",
3243 "Rob Siemborski",
3244 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003245 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003246 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00003247 "Ken Tyler",
3248 "Sven Guckes",
3249 "Florian König",
3250 "Pauli Virtanen",
3251 "Daniele Medri",
3252 "Clement Laforet",
3253 "Tedi Heriyanto",
3254 "Bill Soudan",
3255 "Christian Weisgerber",
3256 "Erik Andersen",
3257 "Big Gaute",
3258 "Joshua Jensen",
3259 "Ryan Krebs",
3260 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003261 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003262 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003263 "Plattsburgh State University",
3264 "Benet Laboratories",
3265 "Amy Allegretta",
3266 "Linda Young",
3267 "Jeremy Robichaud",
3268 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003269 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003270 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003271 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003272 "Thomas Dickey",
3273 "Pavel Curtis",
3274 "Zeyd Ben-Halim",
3275 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003276 NULL, /* "and anyone else we forgot..." */
3277 NULL, /* "Thank you for using nano!" */
3278 "",
3279 "",
3280 "",
3281 "",
David Lawrence Ramsey6481c3f2004-01-09 23:06:54 +00003282 "(c) 1999-2004 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003283 "",
3284 "",
3285 "",
3286 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003287 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003288 };
3289
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003290 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003291 N_("The nano text editor"),
3292 N_("version"),
3293 N_("Brought to you by:"),
3294 N_("Special thanks to:"),
3295 N_("The Free Software Foundation"),
3296 N_("For ncurses:"),
3297 N_("and anyone else we forgot..."),
3298 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003299 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003300
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003301 curs_set(0);
3302 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003303 scrollok(edit, TRUE);
3304 blank_titlebar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003305 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003306 blank_statusbar();
3307 blank_bottombars();
3308 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003309 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003310 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003311
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003312 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
3313 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003314 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003315 if (crpos < CREDIT_LEN) {
3316 const char *what = credits[crpos];
3317 size_t start_x;
3318
3319 if (what == NULL) {
3320 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00003321 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003322 xlpos++;
3323 }
3324 start_x = COLS / 2 - strlen(what) / 2 - 1;
3325 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x, what);
3326 }
3327 napms(700);
3328 scroll(edit);
3329 wrefresh(edit);
3330 if (wgetch(edit) != ERR)
3331 break;
3332 napms(700);
3333 scroll(edit);
3334 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003335 }
3336
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003337 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003338 nodelay(edit, FALSE);
3339 curs_set(1);
3340 display_main_list();
3341 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003342}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003343#endif