blob: da01845279e52191507c046be46dda9ec8b572ad [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * winio.c *
4 * *
David Lawrence Ramseyf28f50e2004-01-09 23:04:55 +00005 * Copyright (C) 1999-2004 Chris Allegretta *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00006 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000022#include "config.h"
23
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000024#include <stdarg.h>
25#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000026#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000027#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000028#include <ctype.h>
Chris Allegretta6232d662002-05-12 19:52:15 +000029#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000030#include "proto.h"
31#include "nano.h"
32
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000033static int statblank = 0; /* Number of keystrokes left after
Chris Allegretta88520c92001-05-05 17:45:54 +000034 we call statusbar(), before we
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000035 actually blank the statusbar */
Robert Siemborskid8510b22000-06-06 23:04:06 +000036
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000037/* Control character compatibility:
38 *
39 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
40 * VT100, and VT220.
41 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
42 * VT220, and VT320.
43 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
44 * VT220, and VT320.
45 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
46 * VT220, and VT320.
47 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
48 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000049 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000050 * ANSI, VT100, and VT220, and which is Backspace under VT320.
51 *
52 * Note: VT220s and VT320s also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000053 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
54 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000055 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000056 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000057 * on which the VT320 sequences are translated by the keypad to KEY_DC
58 * and [nothing]. We work around this conflict via the REBIND_DELETE
59 * flag: if it's not set, we assume VT320 compatibility, and if it is,
60 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
61 * Hemel for helping work this conflict out.
62 *
63 * Escape sequence compatibility:
64 *
65 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
66 * console, the FreeBSD console, the Hurd console (a.k.a. the Mach
67 * console), xterm, rxvt, and Eterm. Among these, there are several
68 * conflicts and omissions, outlined as follows:
69 *
70 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
71 * (Ctrl-I is also Tab on ANSI, which we already support.)
72 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
73 * NumLock off on Linux console; the latter is omitted. (The editing
74 * keypad key is more important to have working than the numeric
75 * keypad key, because the latter actually has no value when NumLock
76 * is off.)
77 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
78 * latter is omitted. (Mouse input will only work properly if the
79 * extended keypad value KEY_MOUSE is generated on mouse events
80 * instead of the escape sequence.)
81 * - F9 on FreeBSD console == PageDown on Hurd console; the former is
82 * omitted. (The editing keypad is more important to have working
83 * than the function keys, because the functions of the former are not
84 * arbitrary and the functions of the latter are.)
85 * - F10 on FreeBSD console == PageUp on Hurd console; the former is
86 * omitted. (Same as above.)
87 * - F13 on FreeBSD console == End on Hurd console; the former is
88 * omitted. (Same as above.)
89 * - The Hurd console has no escape sequences for F11, F12, F13, F14, or
90 * Center (5) on the numeric keypad with NumLock off.
91 *
92 * Note that Center (5) on the numeric keypad with NumLock off can also
93 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +000094
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +000095/* Read in a single input character. If it's ignored, swallow it and go
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +000096 * on. Otherwise, try to translate it from ASCII, extended keypad
97 * values, and/or escape sequences. Supported extended keypad values
98 * consist of [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter,
David Lawrence Ramsey0a258082004-04-23 18:02:37 +000099 * Backspace, the editing keypad (Insert, Delete, Home, End, PageUp, and
100 * PageDown), the function keypad (F1-F14), and the numeric keypad with
101 * NumLock off. Assume nodelay(win) is FALSE. */
David Lawrence Ramsey1576d532004-03-19 21:46:34 +0000102int get_kbinput(WINDOW *win, int *meta_key)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000103{
104 int kbinput, retval;
105
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000106#ifndef NANO_SMALL
107 allow_pending_sigwinch(TRUE);
108#endif
109
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000110 kbinput = get_ignored_kbinput(win);
David Lawrence Ramsey1576d532004-03-19 21:46:34 +0000111 retval = get_accepted_kbinput(win, kbinput, meta_key);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000112
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000113#ifndef NANO_SMALL
114 allow_pending_sigwinch(FALSE);
115#endif
116
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000117 return retval;
118}
119
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000120/* Read in a string of input characters (e.g. an escape sequence)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000121 * verbatim, and return the length of the string in kbinput_len. Assume
122 * nodelay(win) is FALSE. */
David Lawrence Ramsey805547f2004-04-22 03:41:04 +0000123int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len, int
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000124 allow_ascii)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000125{
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000126 int kbinput, *verbatim_kbinput;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000127
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000128#ifndef NANO_SMALL
129 allow_pending_sigwinch(TRUE);
130#endif
131
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +0000132 /* Turn off flow control characters if necessary so that we can type
133 * them in verbatim, and turn the keypad off so that we don't get
134 * extended keypad values outside the ASCII range. */
135 if (ISSET(PRESERVE))
136 disable_flow_control();
David Lawrence Ramseyce991bb2004-03-29 18:36:39 +0000137 keypad(win, FALSE);
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000138
139 kbinput = wgetch(win);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000140 verbatim_kbinput = (int *)nmalloc(sizeof(int));
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000141 verbatim_kbinput[0] = kbinput;
142 *kbinput_len = 1;
143
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000144 if (allow_ascii && kbinput >= '0' && kbinput <= '2')
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000145 /* Entering a three-digit decimal ASCII code from 000-255 in
146 * verbatim mode will produce the corresponding ASCII
147 * character. */
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000148 verbatim_kbinput[0] = get_ascii_kbinput(win, kbinput);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000149 else {
150 nodelay(win, TRUE);
David Lawrence Ramseye1e7cb22004-04-15 06:15:55 +0000151#ifdef DEBUG
152 fprintf(stderr, "get_verbatim_kbinput(): kbinput = %d\n", kbinput);
153#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000154 while ((kbinput = wgetch(win)) != ERR) {
David Lawrence Ramseyda8fd8f2003-09-16 01:22:31 +0000155 (*kbinput_len)++;
David Lawrence Ramsey805547f2004-04-22 03:41:04 +0000156 verbatim_kbinput = (int *)nrealloc(verbatim_kbinput, *kbinput_len * sizeof(int));
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000157 verbatim_kbinput[*kbinput_len - 1] = kbinput;
David Lawrence Ramseye1e7cb22004-04-15 06:15:55 +0000158#ifdef DEBUG
159 fprintf(stderr, "get_verbatim_kbinput(): kbinput = %d\n", kbinput);
160#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000161 }
162 nodelay(win, FALSE);
163 }
164
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +0000165 /* Turn flow control characters back on if necessary and turn the
166 * keypad back on now that we're done. */
167 if (ISSET(PRESERVE))
168 enable_flow_control();
David Lawrence Ramseyce991bb2004-03-29 18:36:39 +0000169 keypad(win, TRUE);
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000170
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000171#ifndef NANO_SMALL
172 allow_pending_sigwinch(FALSE);
173#endif
174
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000175 return verbatim_kbinput;
176}
177
178/* Swallow input characters that should be quietly ignored, and return
179 * the first input character that shouldn't be. */
180int get_ignored_kbinput(WINDOW *win)
181{
182 int kbinput;
183
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +0000184 while (TRUE) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000185 kbinput = wgetch(win);
186 switch (kbinput) {
187 case ERR:
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000188#ifdef KEY_RESIZE
189 /* Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000190 case KEY_RESIZE:
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000191#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000192#ifdef PDCURSES
193 case KEY_SHIFT_L:
194 case KEY_SHIFT_R:
195 case KEY_CONTROL_L:
196 case KEY_CONTROL_R:
197 case KEY_ALT_L:
198 case KEY_ALT_R:
199#endif
200#ifdef DEBUG
201 fprintf(stderr, "get_ignored_kbinput(): kbinput = %d\n", kbinput);
202#endif
203 break;
204 default:
205 return kbinput;
206 }
207 }
208}
209
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000210/* Translate acceptable ASCII, extended keypad values, and/or escape
David Lawrence Ramsey1576d532004-03-19 21:46:34 +0000211 * sequences. Set meta_key to 1 if we get a Meta sequence. Assume
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000212 * nodelay(win) is FALSE. */
David Lawrence Ramsey1576d532004-03-19 21:46:34 +0000213int get_accepted_kbinput(WINDOW *win, int kbinput, int *meta_key)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000214{
David Lawrence Ramsey1576d532004-03-19 21:46:34 +0000215 *meta_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000216
217 switch (kbinput) {
218 case NANO_CONTROL_3: /* Escape */
David Lawrence Ramsey25061362004-01-16 19:12:46 +0000219 kbinput = wgetch(win);
220 switch (kbinput) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000221 case NANO_CONTROL_3: /* Escape */
222 kbinput = wgetch(win);
223 /* Esc Esc [three-digit decimal ASCII code from
224 * 000-255] == [corresponding ASCII character];
David Lawrence Ramseyd390dd82004-02-07 03:38:02 +0000225 * Esc Esc 2 obviously can't be Ctrl-2 here */
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000226 if (kbinput >= '0' && kbinput <= '2')
227 kbinput = get_ascii_kbinput(win, kbinput);
228 /* Esc Esc [character] == Ctrl-[character];
229 * Ctrl-Space (Ctrl-2) == Ctrl-@ == Ctrl-` */
230 else if (kbinput == ' ' || kbinput == '@' || kbinput == '`')
231 kbinput = NANO_CONTROL_SPACE;
232 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
233 else if (kbinput >= '3' && kbinput <= '7')
234 kbinput -= 24;
235 /* Ctrl-8 (Ctrl-?) */
236 else if (kbinput == '8' || kbinput == '?')
237 kbinput = NANO_CONTROL_8;
238 /* Ctrl-A to Ctrl-_ */
239 else if (kbinput >= 'A' && kbinput <= '_')
240 kbinput -= 64;
David Lawrence Ramseyda8fd8f2003-09-16 01:22:31 +0000241 /* Ctrl-A to Ctrl-~ */
242 else if (kbinput >= 'a' && kbinput <= '~')
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000243 kbinput -= 96;
244 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000245 case 'O':
246 case 'o':
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000247 case '[':
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000248 {
David Lawrence Ramsey805547f2004-04-22 03:41:04 +0000249 int old_kbinput = kbinput, *escape_seq;
250 size_t escape_seq_len;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000251 nodelay(win, TRUE);
252 kbinput = wgetch(win);
253 switch (kbinput) {
254 case ERR:
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000255 kbinput = tolower(old_kbinput);
David Lawrence Ramsey1576d532004-03-19 21:46:34 +0000256 *meta_key = TRUE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000257 break;
258 default:
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000259 ungetch(kbinput);
260 ungetch(old_kbinput);
261 escape_seq = get_verbatim_kbinput(win, &escape_seq_len, 0);
262 kbinput = get_escape_seq_kbinput(win, escape_seq, escape_seq_len);
263 free(escape_seq);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000264 }
265 nodelay(win, FALSE);
266 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000267 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000268 default:
269 /* Esc [character] == Meta-[character] */
David Lawrence Ramseyda8fd8f2003-09-16 01:22:31 +0000270 kbinput = tolower(kbinput);
David Lawrence Ramsey1576d532004-03-19 21:46:34 +0000271 *meta_key = TRUE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000272 }
273 break;
David Lawrence Ramsey7776ef92003-11-04 18:32:35 +0000274 case NANO_CONTROL_8:
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000275 kbinput = ISSET(REBIND_DELETE) ? NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
David Lawrence Ramsey7776ef92003-11-04 18:32:35 +0000276 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000277 case KEY_DOWN:
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000278 kbinput = NANO_NEXTLINE_KEY;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000279 break;
280 case KEY_UP:
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000281 kbinput = NANO_PREVLINE_KEY;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000282 break;
283 case KEY_LEFT:
284 kbinput = NANO_BACK_KEY;
285 break;
286 case KEY_RIGHT:
287 kbinput = NANO_FORWARD_KEY;
288 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000289#ifdef KEY_HOME
290 /* HP-UX 10 and 11 don't support KEY_HOME. */
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000291 case KEY_HOME:
292 kbinput = NANO_HOME_KEY;
293 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000294#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000295 case KEY_BACKSPACE:
296 kbinput = NANO_BACKSPACE_KEY;
297 break;
298 case KEY_DC:
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000299 kbinput = ISSET(REBIND_DELETE) ? NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000300 break;
301 case KEY_IC:
302 kbinput = NANO_INSERTFILE_KEY;
303 break;
304 case KEY_NPAGE:
305 kbinput = NANO_NEXTPAGE_KEY;
306 break;
307 case KEY_PPAGE:
308 kbinput = NANO_PREVPAGE_KEY;
309 break;
310 case KEY_ENTER:
311 kbinput = NANO_ENTER_KEY;
312 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000313 case KEY_B2: /* Center (5) on numeric keypad with NumLock off
314 * on xterm. */
315#ifdef KEY_BEG
316 /* Slang doesn't support KEY_BEG. */
317 case KEY_BEG: /* Center (5) on numeric keypad with NumLock off
318 * on Eterm. */
319#endif
320 kbinput = '5';
321 break;
322#ifdef KEY_END
323 /* HP-UX 10 and 11 don't support KEY_END. */
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000324 case KEY_END:
325 kbinput = NANO_END_KEY;
326 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000327#endif
328#ifdef KEY_SUSPEND
329 /* Slang doesn't support KEY_SUSPEND. */
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000330 case KEY_SUSPEND:
331 kbinput = NANO_SUSPEND_KEY;
332 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000333#endif
334#ifdef KEY_SLEFT
335 /* Slang doesn't support KEY_SLEFT. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000336 case KEY_SLEFT:
337 kbinput = NANO_BACK_KEY;
338 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000339#endif
340#ifdef KEY_SRIGHT
341 /* Slang doesn't support KEY_SRIGHT. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000342 case KEY_SRIGHT:
343 kbinput = NANO_FORWARD_KEY;
344 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000345#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000346 }
347#ifdef DEBUG
David Lawrence Ramsey1576d532004-03-19 21:46:34 +0000348 fprintf(stderr, "get_accepted_kbinput(): kbinput = %d, meta_key = %d\n", kbinput, *meta_key);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000349#endif
350 return kbinput;
351}
352
353/* Translate a three-digit decimal ASCII code from 000-255 into the
354 * corresponding ASCII character. */
355int get_ascii_kbinput(WINDOW *win, int kbinput)
356{
357 int retval;
358
359 switch (kbinput) {
360 case '0':
361 case '1':
362 case '2':
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000363 retval = (kbinput - '0') * 100;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000364 break;
365 default:
366 return kbinput;
367 }
368
369 kbinput = wgetch(win);
370 switch (kbinput) {
371 case '0':
372 case '1':
373 case '2':
374 case '3':
375 case '4':
376 case '5':
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000377 retval += (kbinput - '0') * 10;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000378 break;
379 case '6':
380 case '7':
381 case '8':
382 case '9':
383 if (retval < 200) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000384 retval += (kbinput - '0') * 10;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000385 break;
386 }
387 default:
388 return kbinput;
389 }
390
391 kbinput = wgetch(win);
392 switch (kbinput) {
393 case '0':
394 case '1':
395 case '2':
396 case '3':
397 case '4':
398 case '5':
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000399 retval += kbinput - '0';
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000400 break;
401 case '6':
402 case '7':
403 case '8':
404 case '9':
405 if (retval < 250) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000406 retval += kbinput - '0';
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000407 break;
408 }
409 default:
410 return kbinput;
411 }
412
413#ifdef DEBUG
414 fprintf(stderr, "get_ascii_kbinput(): kbinput = %d\n", kbinput);
415#endif
416 return retval;
417}
418
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000419/* Translate escape sequences, most of which correspond to extended
420 * keypad values. These sequences are generated when the terminal
421 * doesn't support the needed keys. Assume that Escape has already been
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000422 * read in, and that nodelay(win) is TRUE. */
David Lawrence Ramsey805547f2004-04-22 03:41:04 +0000423int get_escape_seq_kbinput(WINDOW *win, int *escape_seq, size_t
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000424 escape_seq_len)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000425{
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000426 int kbinput = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000427
428 if (escape_seq_len > 1) {
429 switch (escape_seq[0]) {
430 case 'O':
431 switch (escape_seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000432 case '2':
433 if (escape_seq_len >= 3) {
434 switch (escape_seq[2]) {
435 case 'P': /* Esc O 2 P == F13 on
436 * xterm. */
437 kbinput = KEY_F(13);
438 break;
439 case 'Q': /* Esc O 2 Q == F14 on
440 * xterm. */
441 kbinput = KEY_F(14);
442 break;
443 }
444 }
445 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000446 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
447 case 'B': /* Esc O B == Down on
448 * VT100/VT320/xterm. */
449 case 'C': /* Esc O C == Right on
450 * VT100/VT320/xterm. */
451 case 'D': /* Esc O D == Left on
452 * VT100/VT320/xterm. */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000453 kbinput = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000454 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000455 case 'E': /* Esc O E == Center (5) on numeric keypad
456 * with NumLock off on xterm. */
457 kbinput = '5';
458 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000459 case 'F': /* Esc O F == End on xterm. */
460 kbinput = NANO_END_KEY;
461 break;
462 case 'H': /* Esc O H == Home on xterm. */
463 kbinput = NANO_HOME_KEY;
464 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000465 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000466 * NumLock off on
467 * VT100/VT220/VT320/xterm/Eterm. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000468 kbinput = NANO_ENTER_KEY;
469 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000470 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Hurd
471 * console. */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000472 kbinput = KEY_F(1);
473 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000474 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Hurd
475 * console. */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000476 kbinput = KEY_F(2);
477 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000478 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Hurd
479 * console. */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000480 kbinput = KEY_F(3);
481 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000482 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Hurd
483 * console. */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000484 kbinput = KEY_F(4);
485 break;
486 case 'T': /* Esc O T == F5 on Hurd console. */
487 kbinput = KEY_F(5);
488 break;
489 case 'U': /* Esc O U == F6 on Hurd console. */
490 kbinput = KEY_F(6);
491 break;
492 case 'V': /* Esc O V == F7 on Hurd console. */
493 kbinput = KEY_F(7);
494 break;
495 case 'W': /* Esc O W == F8 on Hurd console. */
496 kbinput = KEY_F(8);
497 break;
498 case 'X': /* Esc O X == F9 on Hurd console. */
499 kbinput = KEY_F(9);
500 break;
501 case 'Y': /* Esc O Y == F10 on Hurd console. */
502 kbinput = KEY_F(10);
503 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000504 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000505 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000506 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000507 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000508 kbinput = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000509 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000510 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000511 * NumLock off on
512 * VT100/VT220/VT320/xterm/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000513 kbinput = '*';
514 break;
515 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000516 * NumLock off on
517 * VT100/VT220/VT320/xterm/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000518 kbinput = '+';
519 break;
520 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000521 * NumLock off on
522 * VT100/VT220/VT320/xterm/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000523 kbinput = '+';
524 break;
525 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000526 * NumLock off on
527 * VT100/VT220/VT320/xterm/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000528 kbinput = '-';
529 break;
530 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000531 * with NumLock off on
532 * VT100/VT220/VT320/xterm/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000533 kbinput = NANO_DELETE_KEY;
534 break;
535 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000536 * NumLock off on
537 * VT100/VT220/VT320/xterm/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000538 kbinput = '/';
539 break;
540 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000541 * with NumLock off on
542 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000543 kbinput = NANO_INSERTFILE_KEY;
544 break;
545 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000546 * with NumLock off on
547 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000548 kbinput = NANO_END_KEY;
549 break;
550 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000551 * with NumLock off on
552 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000553 kbinput = NANO_NEXTLINE_KEY;
554 break;
555 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000556 * keypad with NumLock off on
557 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000558 kbinput = NANO_NEXTPAGE_KEY;
559 break;
560 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000561 * with NumLock off on
562 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000563 kbinput = NANO_BACK_KEY;
564 break;
565 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000566 * with NumLock off on
567 * VT100/VT220/VT320/rxvt/Eterm. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000568 kbinput = '5';
569 break;
570 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000571 * with NumLock off on
572 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000573 kbinput = NANO_FORWARD_KEY;
574 break;
575 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000576 * with NumLock off on
577 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000578 kbinput = NANO_HOME_KEY;
579 break;
580 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000581 * with NumLock off on
582 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000583 kbinput = NANO_PREVLINE_KEY;
584 break;
585 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000586 * with NumLock off on
587 * VT100/VT220/VT320/rxvt. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000588 kbinput = NANO_PREVPAGE_KEY;
589 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000590 }
591 break;
592 case 'o':
593 switch (escape_seq[1]) {
594 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000595 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000596 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000597 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000598 kbinput = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000599 break;
600 }
601 break;
602 case '[':
603 switch (escape_seq[1]) {
604 case '1':
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000605 if (escape_seq_len >= 3) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000606 switch (escape_seq[2]) {
607 case '1': /* Esc [ 1 1 ~ == F1 on
608 * rxvt/Eterm. */
609 kbinput = KEY_F(1);
610 break;
611 case '2': /* Esc [ 1 2 ~ == F2 on
612 * rxvt/Eterm. */
613 kbinput = KEY_F(2);
614 break;
615 case '3': /* Esc [ 1 3 ~ == F3 on
616 * rxvt/Eterm. */
617 kbinput = KEY_F(3);
618 break;
619 case '4': /* Esc [ 1 4 ~ == F4 on
620 * rxvt/Eterm. */
621 kbinput = KEY_F(4);
622 break;
623 case '5': /* Esc [ 1 5 ~ == F5 on
624 * xterm/rxvt/Eterm. */
625 kbinput = KEY_F(5);
626 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000627 case '7': /* Esc [ 1 7 ~ == F6 on
628 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000629 * console/xterm/rxvt/Eterm. */
630 kbinput = KEY_F(6);
631 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000632 case '8': /* Esc [ 1 8 ~ == F7 on
633 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000634 * console/xterm/rxvt/Eterm. */
635 kbinput = KEY_F(7);
636 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000637 case '9': /* Esc [ 1 9 ~ == F8 on
638 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000639 * console/xterm/rxvt/Eterm. */
640 kbinput = KEY_F(8);
641 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000642 case ';':
643 if (escape_seq_len >= 4) {
644 switch (escape_seq[3]) {
645 case '2':
646 if (escape_seq_len >= 5) {
647 switch (escape_seq[4]) {
648 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
649 * xterm. */
650 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
651 * xterm. */
652 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
653 * xterm. */
654 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
655 * xterm. */
656 kbinput = get_escape_seq_abcd(escape_seq[4]);
657 break;
658 }
659 }
660 break;
661 case '5':
662 if (escape_seq_len >= 5) {
663 switch (escape_seq[4]) {
664 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
665 * xterm. */
666 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
667 * xterm. */
668 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
669 * xterm. */
670 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
671 * xterm. */
672 kbinput = get_escape_seq_abcd(escape_seq[4]);
673 break;
674 }
675 }
676 break;
677 }
678 }
679 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000680 default: /* Esc [ 1 ~ == Home on
681 * VT320/Linux console. */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000682 kbinput = NANO_HOME_KEY;
683 break;
684 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000685 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000686 break;
687 case '2':
688 if (escape_seq_len >= 3) {
689 switch (escape_seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000690 case '0': /* Esc [ 2 0 ~ == F9 on
691 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000692 * console/xterm/rxvt/Eterm. */
693 kbinput = KEY_F(9);
694 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000695 case '1': /* Esc [ 2 1 ~ == F10 on
696 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000697 * console/xterm/rxvt/Eterm. */
698 kbinput = KEY_F(10);
699 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000700 case '3': /* Esc [ 2 3 ~ == F11 on
701 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000702 * console/xterm/rxvt/Eterm. */
703 kbinput = KEY_F(11);
704 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000705 case '4': /* Esc [ 2 4 ~ == F12 on
706 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000707 * console/xterm/rxvt/Eterm. */
708 kbinput = KEY_F(12);
709 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000710 case '5': /* Esc [ 2 5 ~ == F13 on
711 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000712 * console/rxvt/Eterm. */
713 kbinput = KEY_F(13);
714 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000715 case '6': /* Esc [ 2 6 ~ == F14 on
716 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000717 * console/rxvt/Eterm. */
718 kbinput = KEY_F(14);
719 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000720 default: /* Esc [ 2 ~ == Insert on
721 * VT220/VT320/Linux
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000722 * console/xterm. */
723 kbinput = NANO_INSERTFILE_KEY;
724 break;
725 }
726 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000727 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000728 case '3': /* Esc [ 3 ~ == Delete on
729 * VT220/VT320/Linux console/xterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000730 kbinput = NANO_DELETE_KEY;
731 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000732 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000733 * console/xterm. */
734 kbinput = NANO_END_KEY;
735 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000736 case '5': /* Esc [ 5 ~ == PageUp on
737 * VT220/VT320/Linux console/xterm; Esc [
738 * 5 ^ == PageUp on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000739 kbinput = NANO_PREVPAGE_KEY;
740 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000741 case '6': /* Esc [ 6 ~ == PageDown on
742 * VT220/VT320/Linux console/xterm; Esc [
743 * 6 ^ == PageDown on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000744 kbinput = NANO_NEXTPAGE_KEY;
745 break;
746 case '7': /* Esc [ 7 ~ == Home on rxvt. */
747 kbinput = NANO_HOME_KEY;
748 break;
749 case '8': /* Esc [ 8 ~ == End on rxvt. */
750 kbinput = NANO_END_KEY;
751 break;
752 case '9': /* Esc [ 9 == Delete on Hurd console. */
753 kbinput = NANO_DELETE_KEY;
754 break;
755 case '@': /* Esc [ @ == Insert on Hurd console. */
756 kbinput = NANO_INSERTFILE_KEY;
757 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000758 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000759 * console/FreeBSD console/Hurd
760 * console/rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000761 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000762 * console/FreeBSD console/Hurd
763 * console/rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000764 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
765 * console/FreeBSD console/Hurd
766 * console/rxvt/Eterm. */
767 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000768 * console/FreeBSD console/Hurd
769 * console/rxvt/Eterm. */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000770 kbinput = get_escape_seq_abcd(escape_seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000771 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000772 case 'E': /* Esc [ E == Center (5) on numeric keypad
773 * with NumLock off on FreeBSD console. */
774 kbinput = '5';
775 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000776 case 'F': /* Esc [ F == End on FreeBSD
777 * console/Eterm. */
778 kbinput = NANO_END_KEY;
779 break;
780 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000781 * console. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000782 kbinput = NANO_NEXTPAGE_KEY;
783 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000784 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000785 * console/Hurd console/Eterm. */
786 kbinput = NANO_HOME_KEY;
787 break;
788 case 'I': /* Esc [ I == PageUp on FreeBSD
789 * console. */
790 kbinput = NANO_PREVPAGE_KEY;
791 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000792 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000793 * console. */
794 kbinput = NANO_INSERTFILE_KEY;
795 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000796 case 'M': /* Esc [ M == F1 on FreeBSD console. */
797 kbinput = KEY_F(1);
798 break;
799 case 'N': /* Esc [ N == F2 on FreeBSD console. */
800 kbinput = KEY_F(2);
801 break;
802 case 'O':
803 if (escape_seq_len >= 3) {
804 switch (escape_seq[2]) {
805 case 'P': /* Esc [ O P == F1 on
806 * xterm. */
807 kbinput = KEY_F(1);
808 break;
809 case 'Q': /* Esc [ O Q == F2 on
810 * xterm. */
811 kbinput = KEY_F(2);
812 break;
813 case 'R': /* Esc [ O R == F3 on
814 * xterm. */
815 kbinput = KEY_F(3);
816 break;
817 case 'S': /* Esc [ O S == F4 on
818 * xterm. */
819 kbinput = KEY_F(4);
820 break;
821 default: /* Esc [ O == F3 on
822 * FreeBSD console. */
823 kbinput = KEY_F(3);
824 break;
825 }
826 }
827 break;
828 case 'P': /* Esc [ P == F4 on FreeBSD console. */
829 kbinput = KEY_F(4);
830 break;
831 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
832 kbinput = KEY_F(5);
833 break;
834 case 'R': /* Esc [ R == F6 on FreeBSD console. */
835 kbinput = KEY_F(6);
836 break;
837 case 'S': /* Esc [ S == F7 on FreeBSD console. */
838 kbinput = KEY_F(7);
839 break;
840 case 'T': /* Esc [ T == F8 on FreeBSD console. */
841 kbinput = KEY_F(8);
842 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000843 case 'U': /* Esc [ U == PageDown on Hurd console. */
844 kbinput = NANO_NEXTPAGE_KEY;
845 break;
846 case 'V': /* Esc [ V == PageUp on Hurd console. */
847 kbinput = NANO_PREVPAGE_KEY;
848 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000849 case 'W': /* Esc [ W == F11 on FreeBSD console. */
850 kbinput = KEY_F(11);
851 break;
852 case 'X': /* Esc [ X == F12 on FreeBSD console. */
853 kbinput = KEY_F(12);
854 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000855 case 'Y': /* Esc [ Y == End on Hurd console. */
856 kbinput = NANO_END_KEY;
857 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000858 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
859 kbinput = KEY_F(14);
860 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +0000861 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +0000862 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +0000863 case 'c': /* Esc [ c == Shift-Right on
864 * rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +0000865 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000866 kbinput = get_escape_seq_abcd(escape_seq[1]);
867 break;
868 case '[':
869 if (escape_seq_len >= 3) {
870 switch (escape_seq[2]) {
871 case 'A': /* Esc [ [ A == F1 on Linux
872 * console. */
873 kbinput = KEY_F(1);
874 break;
875 case 'B': /* Esc [ [ B == F2 on Linux
876 * console. */
877 kbinput = KEY_F(2);
878 break;
879 case 'C': /* Esc [ [ C == F3 on Linux
880 * console. */
881 kbinput = KEY_F(3);
882 break;
883 case 'D': /* Esc [ [ D == F4 on Linux
884 * console. */
885 kbinput = KEY_F(4);
886 break;
887 case 'E': /* Esc [ [ E == F5 on Linux
888 * console. */
889 kbinput = KEY_F(5);
890 break;
891 }
892 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000893 break;
894 }
895 break;
896 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000897 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000898
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000899 if (kbinput == ERR) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000900 /* This escape sequence is unrecognized; send it back. */
901 for (; escape_seq_len > 1; escape_seq_len--)
902 ungetch(escape_seq[escape_seq_len - 1]);
903 kbinput = escape_seq[0];
904 }
905
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000906 return kbinput;
907}
908
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000909/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +0000910 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000911 * to many escape sequences. */
912int get_escape_seq_abcd(int kbinput)
913{
914 switch (tolower(kbinput)) {
915 case 'a':
916 return NANO_PREVLINE_KEY;
917 case 'b':
918 return NANO_NEXTLINE_KEY;
919 case 'c':
920 return NANO_FORWARD_KEY;
921 case 'd':
922 return NANO_BACK_KEY;
923 default:
924 return ERR;
925 }
926}
927
David Lawrence Ramseya593f532003-11-28 19:47:42 +0000928#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000929/* Check for a mouse event, and if one's taken place, save the
930 * coordinates where it took place in mouse_x and mouse_y. After that,
931 * if allow_shortcuts is zero, return 0. Otherwise, if the mouse event
932 * took place on the shortcut list on the bottom two lines of the screen
933 * (assuming that the shortcut list is visible), figure out which
934 * shortcut was clicked and ungetch() the equivalent keystroke(s).
935 * Return 0 if no keystrokes were ungetch()ed, or 1 if at least one was.
936 * Assume that KEY_MOUSE has already been read in. */
937int get_mouseinput(int *mouse_x, int *mouse_y, int allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +0000938{
939 MEVENT mevent;
940
941 *mouse_x = -1;
942 *mouse_y = -1;
943
944 /* First, get the actual mouse event. */
945 if (getmouse(&mevent) == ERR)
946 return 0;
947
948 /* Save the screen coordinates where the mouse event took place. */
949 *mouse_x = mevent.x;
950 *mouse_y = mevent.y;
951
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000952 /* If we're not allowing shortcuts' we're done now. */
953 if (!allow_shortcuts)
954 return 0;
955
956 /* Otherwise, if the current shortcut list is being displayed on the
957 * last two lines of the screen and the mouse event took place
958 * inside it, we need to figure out which shortcut was clicked and
959 * ungetch() the equivalent keystroke(s) for it. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +0000960 if (!ISSET(NO_HELP) && wenclose(bottomwin, *mouse_y, *mouse_x)) {
961 int i, j;
962 int currslen;
963 /* The number of shortcuts in the current shortcut list. */
964 const shortcut *s = currshortcut;
965 /* The actual shortcut we clicked on, starting at the first
966 * one in the current shortcut list. */
967
968 /* Get the shortcut lists' length. */
969 if (currshortcut == main_list)
970 currslen = MAIN_VISIBLE;
971 else
972 currslen = length_of_list(currshortcut);
973
974 /* Calculate the width of each shortcut in the list (it's the
975 * same for all of them). */
976 if (currslen < 2)
977 i = COLS / 6;
978 else
979 i = COLS / ((currslen / 2) + (currslen % 2));
980
981 /* Calculate the y-coordinates relative to the beginning of
982 * bottomwin, i.e, the bottom three lines of the screen. */
983 j = *mouse_y - (editwinrows + 3);
984
985 /* If we're on the statusbar, beyond the end of the shortcut
986 * list, or beyond the end of a shortcut on the right side of
987 * the screen, don't do anything. */
988 if (j < 0 || (*mouse_x / i) >= currslen)
989 return 0;
990 j = (*mouse_x / i) * 2 + j;
991 if (j >= currslen)
992 return 0;
993
994 /* Go through the shortcut list to determine which shortcut was
995 * clicked. */
996 for (; j > 0; j--)
997 s = s->next;
998
David Lawrence Ramsey1576d532004-03-19 21:46:34 +0000999 /* And ungetch() the equivalent control key. If it's a Meta key
1000 * sequence, we need to ungetch() Escape too. Assume that the
1001 * shortcut has an equivalent control key, meta key sequence, or
1002 * both. */
1003 if (s->ctrlval != NANO_NO_KEY)
1004 ungetch(s->ctrlval);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001005 else if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001006 ungetch(s->metaval);
1007 ungetch(NANO_CONTROL_3);
1008 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001009
1010 return 1;
1011 }
1012 return 0;
1013}
1014#endif
1015
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001016int do_first_line(void)
1017{
1018 current = fileage;
1019 placewewant = 0;
1020 current_x = 0;
David Lawrence Ramseyd91ab6e2003-09-07 23:57:24 +00001021 edit_update(current, TOP);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001022 return 1;
1023}
1024
1025int do_last_line(void)
1026{
1027 current = filebot;
1028 placewewant = 0;
1029 current_x = 0;
Chris Allegretta234a34d2000-07-29 04:33:38 +00001030 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001031 return 1;
1032}
1033
Chris Allegretta6df90f52002-07-19 01:08:59 +00001034/* Return the placewewant associated with current_x. That is, xplustabs
1035 * is the zero-based column position of the cursor. Value is no smaller
1036 * than current_x. */
1037size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001038{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001039 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001040}
1041
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001042/* actual_x() gives the index in str of the character displayed at
1043 * column xplus. That is, actual_x() is the largest value such that
1044 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
1045size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001046{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001047 size_t i = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001048 /* the position in str, returned */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001049 size_t length = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001050 /* the screen display width to str[i] */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001051
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001052 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001053
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001054 for (; length < xplus && *str != '\0'; i++, str++) {
1055 if (*str == '\t')
David Lawrence Ramsey0362c582003-09-30 03:31:56 +00001056 length += tabsize - (length % tabsize);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001057 else if (is_cntrl_char((int)*str))
Chris Allegretta6df90f52002-07-19 01:08:59 +00001058 length += 2;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001059 else
1060 length++;
1061 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001062 assert(length == strnlenpt(str - i, i));
1063 assert(i <= strlen(str - i));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001064
Chris Allegretta6df90f52002-07-19 01:08:59 +00001065 if (length > xplus)
1066 i--;
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001067
Chris Allegretta6df90f52002-07-19 01:08:59 +00001068 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00001069}
1070
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00001071/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001072 * columns wide are the first size characters of buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001073size_t strnlenpt(const char *buf, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00001074{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001075 size_t length = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001076
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001077 assert(buf != NULL);
1078 for (; *buf != '\0' && size != 0; size--, buf++) {
1079 if (*buf == '\t')
1080 length += tabsize - (length % tabsize);
1081 else if (is_cntrl_char((int)*buf))
1082 length += 2;
1083 else
1084 length++;
1085 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001086 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001087}
1088
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001089/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001090size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001091{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00001092 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001093}
1094
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001095void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001096{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001097 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001098}
1099
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001100void blank_edit(void)
1101{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001102 size_t i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001103 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001104 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001105}
1106
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001107void blank_statusbar(void)
1108{
1109 mvwaddstr(bottomwin, 0, 0, hblank);
1110}
1111
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001112void check_statblank(void)
1113{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001114 if (statblank > 1)
1115 statblank--;
1116 else if (statblank == 1 && !ISSET(CONSTUPDATE)) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001117 statblank = 0;
1118 blank_statusbar();
1119 wnoutrefresh(bottomwin);
1120 reset_cursor();
1121 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001122 }
1123}
1124
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001125void blank_bottombars(void)
1126{
1127 if (!ISSET(NO_HELP)) {
1128 mvwaddstr(bottomwin, 1, 0, hblank);
1129 mvwaddstr(bottomwin, 2, 0, hblank);
1130 }
1131}
1132
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001133/* Convert buf into a string that can be displayed on screen. The
1134 * caller wants to display buf starting with column start_col, and
1135 * extending for at most len columns. start_col is zero-based. len is
1136 * one-based, so len == 0 means you get "" returned. The returned
1137 * string is dynamically allocated, and should be freed. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001138char *display_string(const char *buf, size_t start_col, size_t len)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001139{
1140 size_t start_index;
1141 /* Index in buf of first character shown in return value. */
1142 size_t column;
1143 /* Screen column start_index corresponds to. */
1144 size_t end_index;
1145 /* Index in buf of last character shown in return value. */
1146 size_t alloc_len;
1147 /* The length of memory allocated for converted. */
1148 char *converted;
1149 /* The string we return. */
1150 size_t index;
1151 /* Current position in converted. */
1152
1153 if (len == 0)
1154 return mallocstrcpy(NULL, "");
1155
1156 start_index = actual_x(buf, start_col);
1157 column = strnlenpt(buf, start_index);
1158 assert(column <= start_col);
1159 end_index = actual_x(buf, start_col + len - 1);
1160 alloc_len = strnlenpt(buf, end_index + 1) - column;
1161 if (len > alloc_len + column - start_col)
1162 len = alloc_len + column - start_col;
1163 converted = charalloc(alloc_len + 1);
1164 buf += start_index;
1165 index = 0;
1166
1167 for (; index < alloc_len; buf++) {
1168 if (*buf == '\t')
1169 do {
1170 converted[index++] = ' ';
1171 } while ((column + index) % tabsize);
1172 else if (is_cntrl_char(*buf)) {
1173 converted[index++] = '^';
1174 if (*buf == '\n')
1175 /* Treat newlines embedded in a line as encoded nulls;
1176 * the line in question should be run through unsunder()
1177 * before reaching here. */
1178 converted[index++] = '@';
1179 else if (*buf == NANO_CONTROL_8)
1180 converted[index++] = '?';
1181 else
1182 converted[index++] = *buf + 64;
1183 } else
1184 converted[index++] = *buf;
1185 }
1186 assert(len <= alloc_len + column - start_col);
1187 charmove(converted, converted + start_col - column, len);
1188 null_at(&converted, len);
1189
1190 return charealloc(converted, len + 1);
1191}
1192
Chris Allegretta7662c862003-01-13 01:35:15 +00001193/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001194 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00001195 *
Chris Allegretta7662c862003-01-13 01:35:15 +00001196 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00001197 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001198void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001199{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001200 size_t x_real = strnlenpt(inputbuf, x);
1201 int wid = COLS - strlen(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00001202
Chris Allegretta6df90f52002-07-19 01:08:59 +00001203 assert(0 <= x && x <= strlen(inputbuf));
1204
Chris Allegrettab3655b42001-10-22 03:15:31 +00001205 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001206 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001207
Chris Allegretta6df90f52002-07-19 01:08:59 +00001208 mvwaddstr(bottomwin, 0, 0, buf);
1209 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001210
1211 if (COLS > 1)
1212 waddch(bottomwin, x_real < wid ? ' ' : '$');
1213 if (COLS > 2) {
1214 size_t page_start = x_real - x_real % wid;
1215 char *expanded = display_string(inputbuf, page_start, wid);
1216
1217 assert(wid > 0);
1218 assert(strlen(expanded) <= wid);
1219 waddstr(bottomwin, expanded);
1220 free(expanded);
1221 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
1222 } else
1223 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001224 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001225}
1226
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00001227/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00001228 * statusq(). */
Chris Allegrettaf717f982003-02-13 22:25:01 +00001229int nanogetstr(int allowtabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00001230#ifndef NANO_SMALL
1231 historyheadtype *history_list,
1232#endif
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001233 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00001234#ifndef DISABLE_TABCOMP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001235 , int *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00001236#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00001237 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00001238{
1239 int kbinput;
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001240 int meta_key;
Chris Allegretta09fc4302003-01-16 22:16:38 +00001241 static int x = -1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001242 /* the cursor position in 'answer' */
1243 int xend;
1244 /* length of 'answer', the status bar text */
1245 int tabbed = 0;
1246 /* used by input_tab() */
1247 const shortcut *t;
Chris Allegretta598106e2002-01-19 01:59:37 +00001248
Chris Allegretta5beed502003-01-05 20:41:21 +00001249#ifndef NANO_SMALL
1250 /* for history */
1251 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00001252 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00001253 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001254 int last_kbinput = 0;
1255
1256 /* This variable is used in the search history code. use_cb == 0
1257 means that we're using the existing history and ignoring
1258 currentbuf. use_cb == 1 means that the entry in answer should be
1259 moved to currentbuf or restored from currentbuf to answer.
1260 use_cb == 2 means that the entry in currentbuf should be moved to
1261 answer or restored from answer to currentbuf. */
1262 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00001263#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001264 xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00001265
1266 /* Only put x at the end of the string if it's uninitialized or if
1267 it would be past the end of the string as it is. Otherwise,
1268 leave it alone. This is so the cursor position stays at the same
1269 place if a prompt-changing toggle is pressed. */
Chris Allegretta65f075d2003-02-13 03:03:49 +00001270 if (x == -1 || x > xend || resetstatuspos)
Chris Allegretta09fc4302003-01-16 22:16:38 +00001271 x = xend;
1272
Chris Allegrettae1e0fd62003-04-15 01:15:09 +00001273 answer = charealloc(answer, xend + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001274 if (xend > 0)
1275 strcpy(answer, def);
1276 else
1277 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001278
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00001279#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001280 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00001281#endif
1282
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001283 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00001284
Chris Allegretta6df90f52002-07-19 01:08:59 +00001285 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001286
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001287 /* Make sure any editor screen updates are displayed before getting
1288 input */
Chris Allegretta022b96f2000-11-14 17:47:58 +00001289 wrefresh(edit);
1290
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001291 while ((kbinput = get_kbinput(bottomwin, &meta_key)) != NANO_ENTER_KEY) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001292 for (t = s; t != NULL; t = t->next) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001293#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001294 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001295#endif
1296
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001297 /* Temporary hack to interpret NANO_HELP_FKEY correctly. */
1298 if (kbinput == t->funcval)
1299 kbinput = t->ctrlval;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00001300
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001301 if (kbinput == t->ctrlval && is_cntrl_char(kbinput)) {
Chris Allegretta5bf51d32000-11-16 06:01:10 +00001302
Chris Allegrettab3655b42001-10-22 03:15:31 +00001303#ifndef DISABLE_HELP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001304 /* Have to do this here, it would be too late to do it
1305 in statusq() */
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00001306 if (kbinput == NANO_HELP_KEY) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00001307 do_help();
1308 break;
1309 }
1310#endif
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001311#ifndef NANO_SMALL
1312 /* Have to handle these here too, for the time being */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001313 if (kbinput == NANO_PREVLINE_KEY || kbinput == NANO_NEXTLINE_KEY)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001314 break;
1315#endif
Chris Allegretta5af58892003-01-17 21:07:38 +00001316
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001317 return t->ctrlval;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001318 }
1319 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001320 assert(0 <= x && x <= xend && xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001321
Chris Allegretta04d848e2000-11-05 17:54:41 +00001322 if (kbinput != '\t')
1323 tabbed = 0;
1324
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001325 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00001326#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001327 case KEY_MOUSE:
1328 do_mouse();
1329 break;
1330#endif
Chris Allegretta658399a2001-06-14 02:54:22 +00001331 case NANO_HOME_KEY:
David Lawrence Ramseyc7acf692004-05-22 20:15:20 +00001332#ifndef NANO_SMALL
1333 if (ISSET(SMART_HOME)) {
1334 int old_x = x;
1335
1336 for (x = 0; isblank(answer[x]) && x < xend; x++)
1337 ;
1338
1339 if (x == old_x || x == xend)
1340 x = 0;
1341 } else
1342#endif
1343 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001344 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00001345 case NANO_END_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001346 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001347 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00001348 case NANO_FORWARD_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001349 if (x < xend)
1350 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001351 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001352 case NANO_DELETE_KEY:
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001353 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1354 if (x < xend) {
1355 charmove(answer + x, answer + x + 1, xend - x);
1356 xend--;
1357 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001358 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001359 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001360 case NANO_CUT_KEY:
1361 case NANO_UNCUT_KEY:
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001362 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1363 null_at(&answer, 0);
1364 xend = 0;
1365 x = 0;
1366 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001367 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001368 case NANO_BACKSPACE_KEY:
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001369 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1370 if (x > 0) {
1371 charmove(answer + x - 1, answer + x, xend - x + 1);
1372 x--;
1373 xend--;
1374 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001375 }
Chris Allegretta04d848e2000-11-05 17:54:41 +00001376 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001377 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001378#ifndef NANO_SMALL
1379 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00001380 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001381 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001382 history_list->current = (historytype *)history_list;
1383 history_list->len = strlen(answer);
1384 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001385
Chris Allegretta7662c862003-01-13 01:35:15 +00001386 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001387 complete = get_history_completion(history_list, answer);
1388 xend = strlen(complete);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001389 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00001390 answer = mallocstrcpy(answer, complete);
1391 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00001392 }
Chris Allegretta5beed502003-01-05 20:41:21 +00001393#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00001394 else
1395#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00001396#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00001397#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00001398 if (allowtabs) {
1399 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00001400
Chris Allegretta327abda2003-01-17 05:04:17 +00001401 answer = input_tab(answer, x, &tabbed, &shift, list);
1402 xend = strlen(answer);
1403 x += shift;
1404 if (x > xend)
1405 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00001406 }
1407#endif
1408 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00001409 case NANO_BACK_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001410 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001411 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001412 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001413 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001414#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00001415 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00001416
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001417 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
1418 isn't NULL, and currentbuf is different from answer,
1419 it means that we're scrolling up at the top of the
1420 search history, and we need to save the current
1421 answer in currentbuf; do this and reset use_cb to
1422 0 */
1423 if (currentbuf == NULL || (use_cb == 1 && strcmp(currentbuf, answer))) {
Chris Allegretta8031f832003-01-09 05:29:58 +00001424 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001425 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00001426 }
1427
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001428 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
1429 is different from answer, it means that we're
1430 scrolling up at the bottom of the search history, and
1431 we need to make the string in currentbuf the current
1432 answer; do this, blow away currentbuf since we don't
1433 need it anymore, and reset use_cb to 0 */
1434 if (currentbuf != NULL && use_cb == 2 && strcmp(currentbuf, answer)) {
1435 answer = mallocstrcpy(answer, currentbuf);
1436 free(currentbuf);
1437 currentbuf = NULL;
1438 xend = strlen(answer);
1439 use_cb = 0;
1440
1441 /* else get older search from the history list and save
1442 it in answer; if there is no older search, blank out
1443 answer */
1444 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001445 answer = mallocstrcpy(answer, history);
1446 xend = strlen(history);
1447 } else {
1448 answer = mallocstrcpy(answer, "");
1449 xend = 0;
1450 }
1451 x = xend;
1452 }
Chris Allegretta5beed502003-01-05 20:41:21 +00001453#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00001454 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001455 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001456#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00001457 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001458
1459 /* get newer search from the history list and save it
1460 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00001461 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001462 answer = mallocstrcpy(answer, history);
1463 xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00001464
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001465 /* if there is no newer search, we're here */
1466
1467 /* if currentbuf isn't NULL and use_cb isn't 2, it means
1468 that we're scrolling down at the bottom of the search
1469 history and we need to make the string in currentbuf
1470 the current answer; do this, blow away currentbuf
1471 since we don't need it anymore, and set use_cb to
1472 1 */
1473 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00001474 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00001475 free(currentbuf);
1476 currentbuf = NULL;
1477 xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001478 use_cb = 1;
1479
1480 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
1481 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00001482 the search history and the current answer (if it's
1483 not blank) needs to be saved in currentbuf; do this,
1484 blank out answer (if necessary), and set use_cb to
1485 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001486 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00001487 if (answer[0] != '\0') {
1488 currentbuf = mallocstrcpy(currentbuf, answer);
1489 answer = mallocstrcpy(answer, "");
1490 }
Chris Allegretta5beed502003-01-05 20:41:21 +00001491 xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001492 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00001493 }
1494 x = xend;
1495 }
1496#endif
1497 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00001498 default:
1499
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001500 for (t = s; t != NULL; t = t->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +00001501#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001502 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
Chris Allegretta598106e2002-01-19 01:59:37 +00001503 kbinput);
Chris Allegretta658399a2001-06-14 02:54:22 +00001504#endif
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001505 if (meta_key == TRUE && (kbinput == t->metaval || kbinput == t->miscval))
David Lawrence Ramsey82138502003-12-24 08:03:54 +00001506 /* We hit a Meta key. Do like above. We don't
1507 * just ungetch() the letter and let it get
1508 * caught above cause that screws the
1509 * keypad... */
1510 return kbinput;
Chris Allegretta658399a2001-06-14 02:54:22 +00001511 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001512
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001513 if (is_cntrl_char(kbinput) || (ISSET(RESTRICTED) && filename[0] != '\0' && s == writefile_list))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001514 break;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001515 answer = charealloc(answer, xend + 2);
David Lawrence Ramsey9eff7462003-09-16 02:04:00 +00001516 charmove(answer + x + 1, answer + x, xend - x + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001517 xend++;
1518 answer[x] = kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001519 x++;
1520
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001521#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001522 fprintf(stderr, "input \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001523#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00001524 } /* switch (kbinput) */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00001525#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00001526 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00001527#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001528 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001529 wrefresh(bottomwin);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001530 } /* while (kbinput ...) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001531
Chris Allegretta5af58892003-01-17 21:07:38 +00001532 /* We finished putting in an answer; reset x */
1533 x = -1;
1534
Chris Allegretta7662c862003-01-13 01:35:15 +00001535 /* Just check for a blank answer here */
Chris Allegretta15c28f82003-01-05 21:47:06 +00001536 if (answer[0] == '\0')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001537 return -2;
1538 else
1539 return 0;
1540}
1541
Chris Allegrettaf717f982003-02-13 22:25:01 +00001542void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001543{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001544 size_t space;
1545 /* The space we have available for display. */
1546 size_t verlen = strlen(VERMSG) + 1;
1547 /* The length of the version message. */
1548 const char *prefix;
1549 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
1550 size_t prefixlen;
1551 /* strlen(prefix) + 1. */
1552 const char *state;
1553 /* "Modified", "View", or spaces the length of "Modified".
1554 * Tells the state of this buffer. */
1555 size_t statelen = 0;
1556 /* strlen(state) + 1. */
1557 char *exppath = NULL;
1558 /* The file name, expanded for display. */
1559 size_t explen = 0;
1560 /* strlen(exppath) + 1. */
1561 int newbuffer = FALSE;
1562 /* Do we say "New Buffer"? */
1563 int dots = FALSE;
1564 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001565
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001566 assert(path != NULL || filename != NULL);
1567 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001568
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001569 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001570
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001571 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001572
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001573 if (COLS <= 5 || COLS - 5 < verlen)
1574 space = 0;
1575 else {
1576 space = COLS - 5 - verlen;
1577 /* Reserve 2/3 of the screen for after the version message. */
1578 if (space < COLS - (COLS / 3))
1579 space = COLS - (COLS / 3);
1580 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001581
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001582 if (COLS > 4) {
1583 /* The version message should only take up 1/3 of the screen. */
1584 mvwaddnstr(topwin, 0, 2, VERMSG, COLS / 3);
1585 waddstr(topwin, " ");
1586 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001587
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001588 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001589 state = _("Modified");
1590 else if (path == NULL && ISSET(VIEW_MODE))
1591 state = _("View");
1592 else {
1593 if (space > 0)
1594 statelen = strnlen(_("Modified"), space - 1) + 1;
1595 state = &hblank[COLS - statelen];
1596 }
1597 statelen = strnlen(state, COLS);
1598 /* We need a space before state. */
1599 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
1600 statelen++;
1601
1602 assert(space >= 0);
1603 if (space == 0 || statelen >= space)
1604 goto the_end;
1605
1606#ifndef DISABLE_BROWSER
1607 if (path != NULL)
1608 prefix = _("DIR:");
1609 else
1610#endif
1611 if (filename[0] == '\0') {
1612 prefix = _("New Buffer");
1613 newbuffer = TRUE;
1614 } else
1615 prefix = _("File:");
1616 assert(statelen < space);
1617 prefixlen = strnlen(prefix, space - statelen);
1618 /* If newbuffer is FALSE, we need a space after prefix. */
1619 if (!newbuffer && prefixlen + statelen < space)
1620 prefixlen++;
1621
1622 if (path == NULL)
1623 path = filename;
David Lawrence Ramsey1dcf36a2004-05-23 21:17:56 +00001624 space -= prefixlen + statelen;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001625 /* space is now the room we have for the file name. */
1626 if (!newbuffer) {
1627 size_t lenpt = strlenpt(path), start_col;
1628
1629 if (lenpt > space)
1630 start_col = actual_x(path, lenpt - space);
1631 else
1632 start_col = 0;
1633 exppath = display_string(path, start_col, space);
1634 dots = (lenpt > space);
1635 explen = strlen(exppath);
1636 }
1637
1638 if (!dots) {
1639 /* There is room for the whole filename, so we center it. */
1640 waddnstr(topwin, hblank, (space - explen) / 3);
1641 waddnstr(topwin, prefix, prefixlen);
1642 if (!newbuffer) {
1643 assert(strlen(prefix) + 1 == prefixlen);
1644 waddch(topwin, ' ');
1645 waddstr(topwin, exppath);
1646 }
1647 } else {
1648 /* We will say something like "File: ...ename". */
1649 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramsey1dcf36a2004-05-23 21:17:56 +00001650 if (space <= 0 || newbuffer)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001651 goto the_end;
1652 waddch(topwin, ' ');
1653 waddnstr(topwin, "...", space);
1654 if (space <= 3)
1655 goto the_end;
1656 space -= 3;
1657 assert(explen = space + 3);
1658 waddnstr(topwin, exppath + 3, space);
1659 }
1660
1661 the_end:
1662
1663 free(exppath);
1664
1665 if (COLS <= 1 || statelen >= COLS - 1)
1666 mvwaddnstr(topwin, 0, 0, state, COLS);
1667 else {
1668 assert(COLS - statelen - 2 >= 0);
1669 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
1670 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
1671 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00001672
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001673 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001674
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001675 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001676 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001677 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001678}
1679
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001680/* If modified is not already set, set it and update titlebar. */
1681void set_modified(void)
1682{
1683 if (!ISSET(MODIFIED)) {
1684 SET(MODIFIED);
1685 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001686 }
1687}
1688
1689void statusbar(const char *msg, ...)
1690{
1691 va_list ap;
1692
1693 va_start(ap, msg);
1694
1695 /* Curses mode is turned off. If we use wmove() now, it will muck
1696 * up the terminal settings. So we just use vfprintf(). */
1697 if (curses_ended) {
1698 vfprintf(stderr, msg, ap);
1699 va_end(ap);
1700 return;
1701 }
1702
1703 /* Blank out the line. */
1704 blank_statusbar();
1705
1706 if (COLS >= 4) {
1707 char *bar;
1708 char *foo;
1709 size_t start_x = 0, foo_len;
1710 bar = charalloc(COLS - 3);
1711 vsnprintf(bar, COLS - 3, msg, ap);
1712 va_end(ap);
1713 foo = display_string(bar, 0, COLS - 4);
1714 free(bar);
1715 foo_len = strlen(foo);
1716 start_x = (COLS - foo_len - 4) / 2;
1717
1718 wmove(bottomwin, 0, start_x);
1719 wattron(bottomwin, A_REVERSE);
1720
1721 waddstr(bottomwin, "[ ");
1722 waddstr(bottomwin, foo);
1723 free(foo);
1724 waddstr(bottomwin, " ]");
1725 wattroff(bottomwin, A_REVERSE);
1726 wnoutrefresh(bottomwin);
1727 reset_cursor();
1728 wrefresh(edit);
1729 /* Leave the cursor at its position in the edit window, not
1730 * in the statusbar. */
1731 }
1732
1733 SET(DISABLE_CURPOS);
1734 statblank = 26;
1735}
1736
Chris Allegretta6232d662002-05-12 19:52:15 +00001737void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001738{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001739 size_t i, colwidth, slen;
1740 char *keystr;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001741
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001742 if (ISSET(NO_HELP))
1743 return;
1744
Chris Allegretta6232d662002-05-12 19:52:15 +00001745 if (s == main_list) {
1746 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001747 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00001748 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00001749 slen = length_of_list(s);
1750
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001751 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00001752 if (slen > MAIN_VISIBLE)
1753 slen = MAIN_VISIBLE;
1754 }
1755
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001756 /* There will be this many characters per column. We need at least
1757 * 3 to display anything properly.*/
1758 colwidth = COLS / ((slen / 2) + (slen % 2));
1759 keystr = charalloc(colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001760
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001761 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00001762
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001763 for (i = 0; i < slen; i++, s = s->next) {
1764 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
Chris Allegretta658399a2001-06-14 02:54:22 +00001765
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001766 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00001767#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001768 if (s->ctrlval == NANO_HISTORY_KEY)
1769 strncpy(keystr, _("Up"), colwidth);
1770 else
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001771#endif
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001772 if (s->ctrlval == NANO_CONTROL_SPACE)
1773 strncpy(keystr, "^ ", colwidth);
1774 else if (s->ctrlval == NANO_CONTROL_8)
1775 strncpy(keystr, "^?", colwidth);
1776 /* Normal values. Assume that the shortcut has an equivalent
1777 * control key, meta key sequence, or both. */
1778 else if (s->ctrlval != NANO_NO_KEY)
1779 snprintf(keystr, colwidth, "^%c", s->ctrlval + 64);
1780 else if (s->metaval != NANO_NO_KEY)
1781 snprintf(keystr, colwidth, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00001782
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001783 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001784 }
1785
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001786 free(keystr);
1787
1788 wnoutrefresh(bottomwin);
1789 reset_cursor();
1790 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001791}
1792
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001793/* Write a shortcut key to the help area at the bottom of the window.
1794 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
1795 * to write at most len characters, even if len is very small and
1796 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
1797 * the whole string! We do not bother padding the entry with blanks. */
1798void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001799{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001800 assert(keystroke != NULL && desc != NULL && len >= 0);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001801 wattron(bottomwin, A_REVERSE);
1802 waddnstr(bottomwin, keystroke, len);
1803 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001804 len -= strlen(keystroke) + 1;
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001805 if (len > 0) {
1806 waddch(bottomwin, ' ');
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001807 waddnstr(bottomwin, desc, len);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001808 }
1809}
1810
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001811/* And so start the display update routines. */
1812
1813#ifndef NDEBUG
1814int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001815{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001816 int check_line = 0;
1817 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00001818
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001819 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
1820 check_line++;
1821 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00001822}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001823#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00001824
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001825/* nano scrolls horizontally within a line in chunks. This function
1826 * returns the column number of the first character displayed in the
1827 * window when the cursor is at the given column. Note that
1828 * 0 <= column - get_page_start(column) < COLS. */
1829size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00001830{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001831 assert(COLS > 0);
1832 if (column == 0 || column < COLS - 1)
1833 return 0;
1834 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00001835 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001836 else if (COLS > 2)
1837 return column - (COLS - 2);
1838 else
1839 return column - (COLS - 1);
1840 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001841}
1842
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00001843/* Resets current_y, based on the position of current, and puts the
1844 * cursor at (current_y, current_x). */
1845void reset_cursor(void)
1846{
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001847 /* Yuck. This condition can be true after open_file() when opening
1848 * the first file. */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00001849 if (edittop == NULL)
1850 return;
1851
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00001852 current_y = current->lineno - edittop->lineno;
1853 if (current_y < editwinrows) {
1854 size_t x = xplustabs();
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00001855
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00001856 wmove(edit, current_y, x - get_page_start(x));
1857 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00001858}
Chris Allegretta6df90f52002-07-19 01:08:59 +00001859
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001860/* edit_add() takes care of the job of actually painting a line into the
1861 * edit window. fileptr is the line to be painted, at row yval of the
1862 * window. converted is the actual string to be written to the window,
1863 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00001864 * characters. start is the column number of the first character of
1865 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001866 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00001867void edit_add(const filestruct *fileptr, const char *converted, int
1868 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001869{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001870#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
1871 size_t startpos = actual_x(fileptr->data, start);
1872 /* The position in fileptr->data of the leftmost character
1873 * that displays at least partially on the window. */
1874 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
1875 /* The position in fileptr->data of the first character that is
1876 * completely off the window to the right.
1877 *
1878 * Note that endpos might be beyond the null terminator of the
1879 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00001880#endif
1881
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001882 assert(fileptr != NULL && converted != NULL);
1883 assert(strlen(converted) <= COLS);
1884
Chris Allegretta2fa11b82001-12-02 04:55:44 +00001885 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001886 * just the text that needs it). */
1887 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00001888
Chris Allegretta7dd77682001-12-08 19:52:28 +00001889#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00001890 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001891 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00001892
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001893 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
1894 int x_start;
1895 /* Starting column for mvwaddnstr. Zero-based. */
1896 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001897 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001898 * characters on a whole line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001899 regmatch_t startmatch; /* match position for start_regexp */
1900 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001901
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001902 if (tmpcolor->bright)
1903 wattron(edit, A_BOLD);
1904 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001905 /* Two notes about regexec(). Return value 0 means there is
1906 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001907 * after the match. */
1908
1909 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001910 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001911 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00001912
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001913 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001914 * last match. Even though two matches may overlap, we
1915 * want to ignore them, so that we can highlight
1916 * C-strings correctly. */
1917 while (k < endpos) {
1918 /* Note the fifth parameter to regexec(). It says
1919 * not to match the beginning-of-line character
1920 * unless k is 0. If regexec() returns REG_NOMATCH,
1921 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00001922 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001923 &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001924 break;
1925 /* Translate the match to the beginning of the line. */
1926 startmatch.rm_so += k;
1927 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00001928 if (startmatch.rm_so == startmatch.rm_eo) {
1929 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00001930 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001931 } else if (startmatch.rm_so < endpos &&
1932 startmatch.rm_eo > startpos) {
1933 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001934 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001935 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00001936 x_start = strnlenpt(fileptr->data,
1937 startmatch.rm_so) - start;
1938 paintlen = strnlenpt(fileptr->data,
1939 startmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001940 if (paintlen > COLS - x_start)
1941 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001942
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001943 assert(0 <= x_start && 0 < paintlen &&
1944 x_start + paintlen <= COLS);
1945 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001946 converted + x_start, paintlen);
1947 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001948 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00001949 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001950 } else {
1951 /* This is a multi-line regexp. There are two steps.
1952 * First, we have to see if the beginning of the line is
1953 * colored by a start on an earlier line, and an end on
1954 * this line or later.
1955 *
1956 * We find the first line before fileptr matching the
1957 * start. If every match on that line is followed by an
1958 * end, then go to step two. Otherwise, find the next line
1959 * after start_line matching the end. If that line is not
1960 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +00001961
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001962 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001963 /* the first line before fileptr matching start */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001964 regoff_t start_col;
1965 /* where it starts in that line */
1966 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001967
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001968 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00001969 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001970 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001971 /* If there is an end on this line, there is no need
1972 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00001973 if (regexec(tmpcolor->end, start_line->data, 0,
1974 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001975 goto step_two;
1976 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001977 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001978 /* No start found, so skip to the next step. */
1979 if (start_line == NULL)
1980 goto step_two;
1981 /* Now start_line is the first line before fileptr
1982 * containing a start match. Is there a start on this
1983 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001984
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001985 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00001986 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001987 start_col += startmatch.rm_so;
1988 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001989 if (regexec(tmpcolor->end,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00001990 start_line->data + start_col + startmatch.rm_eo,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001991 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
1992 REG_NOTBOL) == REG_NOMATCH)
1993 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001994 break;
1995 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +00001996 if (regexec(&tmpcolor->start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00001997 start_line->data + start_col, 1,
1998 &startmatch, REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001999 /* No later start on this line. */
2000 goto step_two;
2001 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002002 /* Indeed, there is a start not followed on this line by
2003 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002004
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002005 /* We have already checked that there is no end before
2006 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002007 * the start at all? We don't paint unterminated
2008 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002009 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002010 while (end_line != NULL &&
2011 regexec(tmpcolor->end, end_line->data, 1, &endmatch, 0))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002012 end_line = end_line->next;
2013
2014 /* No end found, or it is too early. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002015 if (end_line == NULL ||
2016 (end_line == fileptr && endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002017 goto step_two;
2018
2019 /* Now paint the start of fileptr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002020 paintlen = end_line != fileptr ? COLS :
2021 strnlenpt(fileptr->data, endmatch.rm_eo) - start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002022 if (paintlen > COLS)
2023 paintlen = COLS;
2024
2025 assert(0 < paintlen && paintlen <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002026 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002027
2028 /* We have already painted the whole line. */
2029 if (paintlen == COLS)
2030 goto skip_step_two;
2031
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002032 step_two:
2033 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002034 start_col = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002035 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002036 if (regexec(&tmpcolor->start,
2037 fileptr->data + start_col, 1, &startmatch,
2038 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
2039 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002040 /* No more starts on this line. */
2041 break;
2042 /* Translate the match to be relative to the
2043 * beginning of the line. */
2044 startmatch.rm_so += start_col;
2045 startmatch.rm_eo += start_col;
2046
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002047 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002048 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002049 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002050 x_start = strnlenpt(fileptr->data,
2051 startmatch.rm_so) - start;
2052 if (regexec(tmpcolor->end,
2053 fileptr->data + startmatch.rm_eo, 1, &endmatch,
2054 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002055 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002056 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002057 endmatch.rm_so += startmatch.rm_eo;
2058 endmatch.rm_eo += startmatch.rm_eo;
2059 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002060 * appear on this page, and is the match more
2061 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002062 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002063 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002064 paintlen = strnlenpt(fileptr->data,
2065 endmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002066 if (x_start + paintlen > COLS)
2067 paintlen = COLS - x_start;
2068
2069 assert(0 <= x_start && 0 < paintlen &&
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002070 x_start + paintlen <= COLS);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002071 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002072 converted + x_start, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002073 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002074 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002075 /* There is no end on this line. But we haven't
2076 * yet looked for one on later lines. */
2077 end_line = fileptr->next;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002078 while (end_line != NULL &&
2079 regexec(tmpcolor->end, end_line->data, 0,
2080 NULL, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002081 end_line = end_line->next;
2082 if (end_line != NULL) {
2083 assert(0 <= x_start && x_start < COLS);
2084 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002085 converted + x_start, COLS - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002086 /* We painted to the end of the line, so
2087 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002088 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002089 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002090 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002091 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002092 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002093 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002094
Chris Allegrettace452fb2003-02-03 02:56:44 +00002095 skip_step_two:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002096 wattroff(edit, A_BOLD);
2097 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
2098 } /* for tmpcolor in colorstrings */
2099 }
Chris Allegretta598106e2002-01-19 01:59:37 +00002100#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002101
Chris Allegretta7dd77682001-12-08 19:52:28 +00002102#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002103 if (ISSET(MARK_ISSET)
2104 && (fileptr->lineno <= mark_beginbuf->lineno
2105 || fileptr->lineno <= current->lineno)
2106 && (fileptr->lineno >= mark_beginbuf->lineno
2107 || fileptr->lineno >= current->lineno)) {
2108 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002109
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002110 const filestruct *top;
2111 /* Either current or mark_beginbuf, whichever is first. */
2112 size_t top_x;
2113 /* current_x or mark_beginx, corresponding to top. */
2114 const filestruct *bot;
2115 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002116 int x_start;
2117 /* Starting column for mvwaddnstr. Zero-based. */
2118 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002119 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002120 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002121
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002122 mark_order(&top, &top_x, &bot, &bot_x);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002123
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002124 if (top->lineno < fileptr->lineno || top_x < startpos)
2125 top_x = startpos;
2126 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2127 bot_x = endpos;
2128
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002129 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002130 if (top_x < endpos && bot_x > startpos) {
2131 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002132
2133 /* x_start is the expanded location of the beginning of the
2134 * mark minus the beginning of the page. */
2135 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002136
2137 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002138 /* If the end of the mark is off the page, paintlen is
2139 * -1, meaning that everything on the line gets
2140 * painted. */
2141 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002142 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002143 /* Otherwise, paintlen is the expanded location of the
2144 * end of the mark minus the expanded location of the
2145 * beginning of the mark. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002146 paintlen = strnlenpt(fileptr->data, bot_x)
2147 - (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002148
2149 /* If x_start is before the beginning of the page, shift
2150 * paintlen x_start characters to compensate, and put
2151 * x_start at the beginning of the page. */
2152 if (x_start < 0) {
2153 paintlen += x_start;
2154 x_start = 0;
2155 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002156
2157 assert(x_start >= 0 && x_start <= strlen(converted));
2158
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002159 wattron(edit, A_REVERSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002160 mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002161 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002162 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002163 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002164#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002165}
2166
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002167/* Just update one line in the edit buffer. Basically a wrapper for
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002168 * edit_add().
2169 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002170 * If fileptr != current, then index is considered 0. The line will be
2171 * displayed starting with fileptr->data[index]. Likely args are
2172 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002173void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002174{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002175 int line;
2176 /* line in the edit window for CURSES calls */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002177 char *converted;
2178 /* fileptr->data converted to have tabs and control characters
2179 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002180 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002181
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002182 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002183
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002184 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002185
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002186 /* We assume the line numbers are valid. Is that really true? */
2187 assert(line < 0 || line == check_linenumbers(fileptr));
2188
2189 if (line < 0 || line >= editwinrows)
2190 return;
2191
2192 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002193 mvwaddstr(edit, line, 0, hblank);
2194
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002195 /* Next, convert variables that index the line to their equivalent
2196 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002197 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002198 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002199
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002200 /* Expand the line, replacing Tab by spaces, and control characters
2201 * by their display form. */
2202 converted = display_string(fileptr->data, page_start, COLS);
Robert Siemborski53875912000-06-16 04:25:30 +00002203
Chris Allegretta4dc03d52002-05-11 03:04:44 +00002204 /* Now, paint the line */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002205 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002206 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002207
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002208 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002209 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002210 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002211 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002212}
2213
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002214/* This function updates current, based on where current_y is;
2215 * reset_cursor() does the opposite. */
2216void update_cursor(void)
2217{
2218 int i = 0;
2219
2220#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002221 fprintf(stderr, "Moved to (%d, %d) in edit buffer\n", current_y,
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002222 current_x);
2223#endif
2224
2225 current = edittop;
2226 while (i < current_y && current->next != NULL) {
2227 current = current->next;
2228 i++;
2229 }
2230
2231#ifdef DEBUG
Chris Allegretta0e86e602003-01-23 04:27:23 +00002232 fprintf(stderr, "current->data = \"%s\"\n", current->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002233#endif
2234}
2235
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002236void center_cursor(void)
2237{
2238 current_y = editwinrows / 2;
2239 wmove(edit, current_y, current_x);
2240}
2241
Chris Allegretta6df90f52002-07-19 01:08:59 +00002242/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002243void edit_refresh(void)
2244{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002245 /* Neither of these conditions should occur, but they do. edittop
2246 * is NULL when you open an existing file on the command line, and
Chris Allegretta6df90f52002-07-19 01:08:59 +00002247 * ENABLE_COLOR is defined. Yuck. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002248 if (current == NULL)
2249 return;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002250 if (edittop == NULL)
2251 edittop = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002252
Chris Allegretta63d0b482003-01-26 19:47:10 +00002253 if (current->lineno < edittop->lineno ||
2254 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002255 /* Note that edit_update() changes edittop so that
2256 * current->lineno = edittop->lineno + editwinrows / 2. Thus
2257 * when it then calls edit_refresh(), there is no danger of
2258 * getting an infinite loop. */
Chris Allegrettada721be2000-07-31 01:26:42 +00002259 edit_update(current, CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002260 else {
2261 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002262 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002263
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002264#ifdef DEBUG
2265 fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", edittop->lineno);
2266#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002267
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002268 while (nlines < editwinrows) {
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002269 update_line(foo, current_x);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002270 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002271 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002272 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002273 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002274 }
2275 while (nlines < editwinrows) {
2276 mvwaddstr(edit, nlines, 0, hblank);
2277 nlines++;
2278 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002279 reset_cursor();
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002280
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002281 /* What the hell are we expecting to update the screen if this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002282 * isn't here? Luck? */
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002283 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002284 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002285}
2286
Chris Allegretta7662c862003-01-13 01:35:15 +00002287/* Same as above, but touch the window first, so everything is
2288 * redrawn. */
Chris Allegrettaf1d33d32000-08-19 03:53:39 +00002289void edit_refresh_clearok(void)
2290{
2291 clearok(edit, TRUE);
2292 edit_refresh();
2293 clearok(edit, FALSE);
2294}
2295
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002296/* Nice generic routine to update the edit buffer, given a pointer to the
2297 * file struct =) */
David Lawrence Ramsey1356a0a2003-09-10 20:31:02 +00002298void edit_update(filestruct *fileptr, topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002299{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002300 if (fileptr == NULL)
2301 return;
2302
Chris Allegretta6df90f52002-07-19 01:08:59 +00002303 if (location != TOP) {
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002304 int goal = (location == NONE) ? current_y : editwinrows / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002305
David Lawrence Ramseyd91ab6e2003-09-07 23:57:24 +00002306 for (; goal > 0 && fileptr->prev != NULL; goal--)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002307 fileptr = fileptr->prev;
2308 }
2309 edittop = fileptr;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002310 edit_refresh();
2311}
2312
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002313/* Ask a question on the statusbar. Answer will be stored in answer
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002314 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
Chris Allegretta88520c92001-05-05 17:45:54 +00002315 * otherwise, the valid shortcut key caught. Def is any editable text we
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002316 * want to put up by default.
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002317 *
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002318 * New arg tabs tells whether or not to allow tab completion. */
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002319int statusq(int allowtabs, const shortcut *s, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002320#ifndef NANO_SMALL
2321 historyheadtype *which_history,
2322#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00002323 const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002324{
2325 va_list ap;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002326 char *foo = charalloc(COLS - 3);
Chris Allegretta9caa1932002-02-15 20:08:05 +00002327 int ret;
Chris Allegretta2084acc2001-11-29 03:43:08 +00002328#ifndef DISABLE_TABCOMP
Chris Allegrettaa16e4e92002-01-05 18:59:54 +00002329 int list = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00002330#endif
2331
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002332 bottombars(s);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002333
2334 va_start(ap, msg);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002335 vsnprintf(foo, COLS - 4, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002336 va_end(ap);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002337 foo[COLS - 4] = '\0';
Chris Allegretta8ce24132001-04-30 11:28:46 +00002338
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002339 ret = nanogetstr(allowtabs, foo, def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002340#ifndef NANO_SMALL
2341 which_history,
Chris Allegretta2084acc2001-11-29 03:43:08 +00002342#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002343 s
2344#ifndef DISABLE_TABCOMP
2345 , &list
2346#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002347 );
Chris Allegretta6df90f52002-07-19 01:08:59 +00002348 free(foo);
Chris Allegretta65f075d2003-02-13 03:03:49 +00002349 resetstatuspos = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002350
2351 switch (ret) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002352 case NANO_FIRSTLINE_KEY:
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002353 case NANO_FIRSTLINE_FKEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002354 do_first_line();
Chris Allegretta65f075d2003-02-13 03:03:49 +00002355 resetstatuspos = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002356 break;
2357 case NANO_LASTLINE_KEY:
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002358 case NANO_LASTLINE_FKEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002359 do_last_line();
Chris Allegretta65f075d2003-02-13 03:03:49 +00002360 resetstatuspos = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002361 break;
David Lawrence Ramsey8faf3052003-09-04 20:25:29 +00002362#ifndef DISABLE_JUSTIFY
2363 case NANO_PARABEGIN_KEY:
2364 do_para_begin();
2365 resetstatuspos = 1;
2366 break;
2367 case NANO_PARAEND_KEY:
2368 do_para_end();
2369 resetstatuspos = 1;
2370 break;
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002371 case NANO_FULLJUSTIFY_KEY:
2372 do_full_justify();
2373 resetstatuspos = 1;
2374 break;
David Lawrence Ramsey8faf3052003-09-04 20:25:29 +00002375#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002376 case NANO_CANCEL_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00002377 ret = -1;
Chris Allegretta65f075d2003-02-13 03:03:49 +00002378 resetstatuspos = 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002379 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002380 }
Chris Allegrettaa90d0cf2003-02-10 02:55:03 +00002381 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002382
2383#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002384 fprintf(stderr, "I got \"%s\"\n", answer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002385#endif
2386
Chris Allegretta6df90f52002-07-19 01:08:59 +00002387#ifndef DISABLE_TABCOMP
2388 /* if we've done tab completion, there might be a list of
2389 filename matches on the edit window at this point; make sure
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002390 they're cleared off. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002391 if (list)
2392 edit_refresh();
2393#endif
2394
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002395 return ret;
2396}
2397
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002398/* Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00002399 * for N, 2 for All (if all is nonzero when passed in) and -1 for abort
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002400 * (^C). */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002401int do_yesno(int all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002402{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002403 int ok = -2, width = 16;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002404 const char *yesstr; /* String of yes characters accepted */
2405 const char *nostr; /* Same for no */
2406 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00002407
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002408 /* Yes, no and all are strings of any length. Each string consists
2409 * of all characters accepted as a valid character for that value.
2410 * The first value will be the one displayed in the shortcuts. */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002411 yesstr = _("Yy");
2412 nostr = _("Nn");
2413 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002414
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002415 /* Remove gettext() call for keybindings until we clear the thing
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002416 * up. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002417 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002418 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00002419
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002420 if (COLS < 32)
2421 width = COLS / 2;
2422
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002423 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00002424 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002425
Chris Allegretta6232d662002-05-12 19:52:15 +00002426 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00002427 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002428 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002429
2430 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002431 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00002432 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002433 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002434 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002435
Chris Allegrettadb28e962003-01-28 01:23:40 +00002436 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00002437 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002438 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002439
Chris Allegrettadb28e962003-01-28 01:23:40 +00002440 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002441 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002442 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00002443
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002444 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002445
2446 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002447 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002448
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002449 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002450
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002451 wrefresh(bottomwin);
2452
Chris Allegrettadb28e962003-01-28 01:23:40 +00002453 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002454 int kbinput;
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00002455 int meta_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00002456#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002457 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00002458#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002459
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00002460 kbinput = get_kbinput(edit, &meta_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002461
2462 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00002463 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00002464#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002465 /* Look ma! We get to duplicate lots of code from
2466 * do_mouse()!! */
2467 else if (kbinput == KEY_MOUSE) {
2468 kbinput = get_mouseinput(&mouse_x, &mouse_y, 0);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002469
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002470 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
2471 wenclose(bottomwin, mouse_y, mouse_x) && mouse_x <
2472 (width * 2) && mouse_y >= editwinrows + 3) {
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00002473
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002474 int x = mouse_x / width;
2475 /* Did we click in the first column of shortcuts, or
2476 * the second? */
2477 int y = mouse_y - editwinrows - 3;
2478 /* Did we click in the first row of shortcuts? */
2479
2480 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
2481
2482 /* x = 0 means they clicked Yes or No.
2483 * y = 0 means Yes or All. */
2484 ok = -2 * x * y + x - y + 1;
2485
2486 if (ok == 2 && !all)
2487 ok = -2;
2488 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002489 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00002490#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002491 /* Look for the kbinput in the yes, no and (optionally) all
2492 * str. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00002493 else if (strchr(yesstr, kbinput) != NULL)
2494 ok = 1;
2495 else if (strchr(nostr, kbinput) != NULL)
2496 ok = 0;
2497 else if (all && strchr(allstr, kbinput) != NULL)
2498 ok = 2;
2499 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002500
Chris Allegrettadb28e962003-01-28 01:23:40 +00002501 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002502}
2503
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002504int total_refresh(void)
2505{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002506 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002507 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002508 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002509 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002510 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002511 wnoutrefresh(bottomwin);
2512 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002513 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002514 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002515 clearok(bottomwin, FALSE);
2516 edit_refresh();
2517 titlebar(NULL);
2518 return 1;
2519}
2520
2521void display_main_list(void)
2522{
2523 bottombars(main_list);
2524}
2525
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002526/* If constant is FALSE, the user typed ^C so we unconditionally display
Chris Allegrettad26ab912003-01-28 01:16:47 +00002527 * the cursor position. Otherwise, we display it only if the character
2528 * position changed, and DISABLE_CURPOS is not set.
2529 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002530 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
2531 * old_i and old_totsize. That way, we leave the current statusbar
2532 * alone, but next time we will display. */
Chris Allegretta2084acc2001-11-29 03:43:08 +00002533int do_cursorpos(int constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002534{
Chris Allegrettad26ab912003-01-28 01:16:47 +00002535 const filestruct *fileptr;
2536 unsigned long i = 0;
2537 static unsigned long old_i = 0;
2538 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002539
Chris Allegrettad26ab912003-01-28 01:16:47 +00002540 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00002541
2542 if (old_totsize == -1)
2543 old_totsize = totsize;
2544
Chris Allegrettad26ab912003-01-28 01:16:47 +00002545 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
2546 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00002547 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00002548 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00002549 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00002550
Chris Allegrettad26ab912003-01-28 01:16:47 +00002551 if (constant && ISSET(DISABLE_CURPOS)) {
2552 UNSET(DISABLE_CURPOS);
2553 old_i = i;
2554 old_totsize = totsize;
2555 return 0;
2556 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00002557
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00002558 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002559 * unconditionally; otherwise, only display the position when the
2560 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00002561 if (!constant || old_i != i || old_totsize != totsize) {
2562 unsigned long xpt = xplustabs() + 1;
2563 unsigned long cur_len = strlenpt(current->data) + 1;
2564 int linepct = 100 * current->lineno / totlines;
2565 int colpct = 100 * xpt / cur_len;
2566 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
2567
2568 statusbar(
2569 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
2570 current->lineno, totlines, linepct,
2571 xpt, cur_len, colpct,
2572 i, totsize, bytepct);
2573 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00002574 }
2575
2576 old_i = i;
2577 old_totsize = totsize;
2578
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002579 reset_cursor();
Chris Allegrettad26ab912003-01-28 01:16:47 +00002580 return 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002581}
2582
Chris Allegretta2084acc2001-11-29 03:43:08 +00002583int do_cursorpos_void(void)
2584{
2585 return do_cursorpos(0);
2586}
2587
Chris Allegretta4640fe32003-02-10 03:10:03 +00002588/* Calculate the next line of help_text, starting at ptr. */
2589int line_len(const char *ptr)
2590{
2591 int j = 0;
2592
2593 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
2594 ptr++;
2595 j++;
2596 }
2597 if (j == COLS - 5) {
2598 /* Don't wrap at the first of two spaces following a period. */
2599 if (*ptr == ' ' && *(ptr + 1) == ' ')
2600 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002601 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00002602 while (*ptr != ' ' && j > 0) {
2603 ptr--;
2604 j--;
2605 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002606 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00002607 if (j == 0)
2608 j = COLS - 5;
2609 }
2610 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
2611 return j;
2612}
2613
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00002614#ifndef DISABLE_HELP
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002615/* Our shortcut-list-compliant help function, which is better than
2616 * nothing, and dynamic! */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002617int do_help(void)
2618{
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00002619 int i, page = 0, kbinput = ERR, meta_key, no_more = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002620 int no_help_flag = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002621 const shortcut *oldshortcut;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002622
2623 blank_edit();
2624 curs_set(0);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002625 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002626 blank_statusbar();
2627
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002628 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00002629 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00002630 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002631
2632 oldshortcut = currshortcut;
Chris Allegrettab3655b42001-10-22 03:15:31 +00002633
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002634 currshortcut = help_list;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002635
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002636 if (ISSET(NO_HELP)) {
2637
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002638 /* Well, if we're going to do this, we should at least do it the
2639 * right way. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002640 no_help_flag = TRUE;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002641 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00002642 window_init();
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002643 bottombars(help_list);
Chris Allegretta70444892001-01-07 23:02:02 +00002644
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002645 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002646 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002647
2648 do {
Chris Allegrettaf717f982003-02-13 22:25:01 +00002649 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00002650
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002651 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00002652#ifndef DISABLE_MOUSE
Chris Allegretta598106e2002-01-19 01:59:37 +00002653 case KEY_MOUSE:
2654 do_mouse();
2655 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002656#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002657 case NANO_NEXTPAGE_KEY:
2658 case NANO_NEXTPAGE_FKEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002659 if (!no_more) {
2660 blank_edit();
2661 page++;
2662 }
2663 break;
2664 case NANO_PREVPAGE_KEY:
2665 case NANO_PREVPAGE_FKEY:
Chris Allegretta4640fe32003-02-10 03:10:03 +00002666 if (page > 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002667 no_more = 0;
2668 blank_edit();
2669 page--;
2670 }
2671 break;
2672 }
2673
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002674 /* Calculate where in the text we should be, based on the
2675 * page. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00002676 for (i = 1; i < page * (editwinrows - 1); i++) {
2677 ptr += line_len(ptr);
2678 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002679 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002680 }
2681
Chris Allegretta4640fe32003-02-10 03:10:03 +00002682 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
2683 int j = line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002684
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002685 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00002686 ptr += j;
2687 if (*ptr == '\n')
2688 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002689 }
Chris Allegretta4640fe32003-02-10 03:10:03 +00002690
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002691 if (*ptr == '\0') {
2692 no_more = 1;
2693 continue;
2694 }
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00002695 } while ((kbinput = get_kbinput(edit, &meta_key)) != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00002696
Chris Allegrettab3655b42001-10-22 03:15:31 +00002697 currshortcut = oldshortcut;
Chris Allegrettab3655b42001-10-22 03:15:31 +00002698
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002699 if (no_help_flag) {
Chris Allegretta70444892001-01-07 23:02:02 +00002700 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002701 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002702 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00002703 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00002704 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002705 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002706
2707 curs_set(1);
2708 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002709
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00002710 /* The help_init() at the beginning allocated help_text, which has
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002711 * now been written to the screen. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00002712 free(help_text);
2713 help_text = NULL;
2714
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002715 return 1;
2716}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00002717#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002718
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002719/* Highlight the current word being replaced or spell checked. We
2720 * expect word to have tabs and control characters expanded. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002721void do_replace_highlight(int highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00002722{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002723 int y = xplustabs();
2724 size_t word_len = strlen(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00002725
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002726 y = get_page_start(y) + COLS - y;
2727 /* Now y is the number of characters we can display on this
2728 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00002729
2730 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00002731
Chris Allegrettafb62f732000-12-05 11:36:41 +00002732 if (highlight_flag)
2733 wattron(edit, A_REVERSE);
2734
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00002735#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00002736 /* This is so we can show zero-length regexes. */
2737 if (word_len == 0)
2738 waddstr(edit, " ");
2739 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00002740#endif
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00002741 waddnstr(edit, word, y - 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002742
2743 if (word_len > y)
2744 waddch(edit, '$');
2745 else if (word_len == y)
2746 waddch(edit, word[word_len - 1]);
Chris Allegrettafb62f732000-12-05 11:36:41 +00002747
2748 if (highlight_flag)
2749 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00002750}
2751
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002752#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002753/* Dump the passed-in file structure to stderr. */
2754void dump_buffer(const filestruct *inptr)
2755{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002756 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00002757 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002758 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00002759 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002760 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00002761 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002762
2763 while (inptr != NULL) {
2764 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
2765 inptr = inptr->next;
2766 }
2767}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002768
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002769/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00002770void dump_buffer_reverse(void)
2771{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002772 const filestruct *fileptr = filebot;
2773
2774 while (fileptr != NULL) {
2775 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
2776 fileptr = fileptr->prev;
2777 }
2778}
2779#endif /* DEBUG */
2780
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002781#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00002782#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00002783#define XLCREDIT_LEN 8
2784
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00002785/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002786void do_credits(void)
2787{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002788 int crpos = 0, xlpos = 0;
2789 const char *credits[CREDIT_LEN] = {
2790 NULL, /* "The nano text editor" */
2791 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00002792 VERSION,
2793 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002794 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00002795 "Chris Allegretta",
2796 "Jordi Mallach",
2797 "Adam Rogoyski",
2798 "Rob Siemborski",
2799 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002800 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00002801 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00002802 "Ken Tyler",
2803 "Sven Guckes",
2804 "Florian König",
2805 "Pauli Virtanen",
2806 "Daniele Medri",
2807 "Clement Laforet",
2808 "Tedi Heriyanto",
2809 "Bill Soudan",
2810 "Christian Weisgerber",
2811 "Erik Andersen",
2812 "Big Gaute",
2813 "Joshua Jensen",
2814 "Ryan Krebs",
2815 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00002816 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002817 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00002818 "Plattsburgh State University",
2819 "Benet Laboratories",
2820 "Amy Allegretta",
2821 "Linda Young",
2822 "Jeremy Robichaud",
2823 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002824 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00002825 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002826 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00002827 "Thomas Dickey",
2828 "Pavel Curtis",
2829 "Zeyd Ben-Halim",
2830 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002831 NULL, /* "and anyone else we forgot..." */
2832 NULL, /* "Thank you for using nano!" */
2833 "",
2834 "",
2835 "",
2836 "",
David Lawrence Ramsey6481c3f2004-01-09 23:06:54 +00002837 "(c) 1999-2004 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002838 "",
2839 "",
2840 "",
2841 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00002842 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002843 };
2844
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002845 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00002846 "The nano text editor",
2847 "version",
2848 "Brought to you by:",
2849 "Special thanks to:",
2850 "The Free Software Foundation",
2851 "For ncurses:",
2852 "and anyone else we forgot...",
2853 "Thank you for using nano!"
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002854 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00002855
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002856 curs_set(0);
2857 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002858 scrollok(edit, TRUE);
2859 blank_titlebar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00002860 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002861 blank_statusbar();
2862 blank_bottombars();
2863 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00002864 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002865 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002866
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002867 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
2868 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002869 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002870 if (crpos < CREDIT_LEN) {
2871 const char *what = credits[crpos];
2872 size_t start_x;
2873
2874 if (what == NULL) {
2875 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00002876 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002877 xlpos++;
2878 }
2879 start_x = COLS / 2 - strlen(what) / 2 - 1;
2880 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x, what);
2881 }
2882 napms(700);
2883 scroll(edit);
2884 wrefresh(edit);
2885 if (wgetch(edit) != ERR)
2886 break;
2887 napms(700);
2888 scroll(edit);
2889 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002890 }
2891
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002892 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002893 nodelay(edit, FALSE);
2894 curs_set(1);
2895 display_main_list();
2896 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00002897}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002898#endif