blob: 1f9664d3d3a36c3772e908f4ca32b432daf4c21c [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * winio.c *
4 * *
Chris Allegrettad757e252003-01-15 19:33:27 +00005 * Copyright (C) 1999-2003 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 Ramsey4d7c2602003-08-17 02:48:43 +000037/* Read in a single input character. If it's ignored, swallow it and go
38 * on. Otherwise, try to translate it from ASCII and extended (keypad)
39 * input. Assume nodelay(win) is FALSE. */
40int get_kbinput(WINDOW *win, int *meta, int rebind_delete)
41{
42 int kbinput, retval;
43
44 kbinput = get_ignored_kbinput(win);
45 retval = get_accepted_kbinput(win, kbinput, meta, rebind_delete);
46
47 return retval;
48}
49
50/* Read in a string of input characters (e. g. an escape sequence)
51 * verbatim, and return the length of the string in kbinput_len. Assume
52 * nodelay(win) is FALSE. */
53char *get_verbatim_kbinput(WINDOW *win, int *kbinput_len)
54{
55 char *verbatim_kbinput;
56 int kbinput = wgetch(win);
57
58 verbatim_kbinput = charalloc(1);
59 verbatim_kbinput[0] = kbinput;
60 *kbinput_len = 1;
61
62 if (kbinput >= '0' && kbinput <= '2')
63 /* Entering a three-digit decimal ASCII code from 000-255 in
64 * verbatim mode will produce the corresponding ASCII
65 * character. */
66 verbatim_kbinput[0] = (char)get_ascii_kbinput(win, kbinput);
67 else {
68 nodelay(win, TRUE);
69 while ((kbinput = wgetch(win)) != ERR) {
David Lawrence Ramseyda8fd8f2003-09-16 01:22:31 +000070 (*kbinput_len)++;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +000071 verbatim_kbinput = charealloc(verbatim_kbinput, *kbinput_len);
72 verbatim_kbinput[*kbinput_len - 1] = (char)kbinput;
73 }
74 nodelay(win, FALSE);
75 }
76
77#ifdef DEBUG
78 fprintf(stderr, "get_verbatim_kbinput(): verbatim_kbinput = %s\n", verbatim_kbinput);
79#endif
80 return verbatim_kbinput;
81}
82
83/* Swallow input characters that should be quietly ignored, and return
84 * the first input character that shouldn't be. */
85int get_ignored_kbinput(WINDOW *win)
86{
87 int kbinput;
88
89 while (1) {
90 kbinput = wgetch(win);
91 switch (kbinput) {
92 case ERR:
93 case KEY_RESIZE:
94#ifdef PDCURSES
95 case KEY_SHIFT_L:
96 case KEY_SHIFT_R:
97 case KEY_CONTROL_L:
98 case KEY_CONTROL_R:
99 case KEY_ALT_L:
100 case KEY_ALT_R:
101#endif
102#ifdef DEBUG
103 fprintf(stderr, "get_ignored_kbinput(): kbinput = %d\n", kbinput);
104#endif
105 break;
106 default:
107 return kbinput;
108 }
109 }
110}
111
112/* Translate acceptable ASCII and extended (keypad) input. Set meta to
113 * 1 if we get a Meta sequence. Assume nodelay(win) is FALSE. */
114int get_accepted_kbinput(WINDOW *win, int kbinput, int *meta,
115 int rebind_delete)
116{
117 *meta = 0;
118
119 switch (kbinput) {
120 case NANO_CONTROL_3: /* Escape */
121 switch (kbinput = wgetch(win)) {
122 case NANO_CONTROL_3: /* Escape */
123 kbinput = wgetch(win);
124 /* Esc Esc [three-digit decimal ASCII code from
125 * 000-255] == [corresponding ASCII character];
126 Esc Esc 2 obviously can't be Ctrl-2 here */
127 if (kbinput >= '0' && kbinput <= '2')
128 kbinput = get_ascii_kbinput(win, kbinput);
129 /* Esc Esc [character] == Ctrl-[character];
130 * Ctrl-Space (Ctrl-2) == Ctrl-@ == Ctrl-` */
131 else if (kbinput == ' ' || kbinput == '@' || kbinput == '`')
132 kbinput = NANO_CONTROL_SPACE;
133 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
134 else if (kbinput >= '3' && kbinput <= '7')
135 kbinput -= 24;
136 /* Ctrl-8 (Ctrl-?) */
137 else if (kbinput == '8' || kbinput == '?')
138 kbinput = NANO_CONTROL_8;
139 /* Ctrl-A to Ctrl-_ */
140 else if (kbinput >= 'A' && kbinput <= '_')
141 kbinput -= 64;
David Lawrence Ramseyda8fd8f2003-09-16 01:22:31 +0000142 /* Ctrl-A to Ctrl-~ */
143 else if (kbinput >= 'a' && kbinput <= '~')
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000144 kbinput -= 96;
145 break;
146 /* Terminal breakage, part 1: We shouldn't get an escape
147 * sequence here for terminals that support Delete, but
148 * we do sometimes on FreeBSD. Thank you, Wouter van
149 * Hemel. */
150 case '[':
151 nodelay(win, TRUE);
152 kbinput = wgetch(win);
153 switch (kbinput) {
154 case ERR:
155 kbinput = '[';
156 *meta = 1;
157 break;
158 default:
159 kbinput = get_escape_seq_kbinput(win, kbinput);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000160 }
161 nodelay(win, FALSE);
162 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000163 default:
164 /* Esc [character] == Meta-[character] */
David Lawrence Ramseyda8fd8f2003-09-16 01:22:31 +0000165 kbinput = tolower(kbinput);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000166 *meta = 1;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000167 }
168 break;
169 case KEY_DOWN:
170 kbinput = NANO_DOWN_KEY;
171 break;
172 case KEY_UP:
173 kbinput = NANO_UP_KEY;
174 break;
175 case KEY_LEFT:
176 kbinput = NANO_BACK_KEY;
177 break;
178 case KEY_RIGHT:
179 kbinput = NANO_FORWARD_KEY;
180 break;
181 case KEY_HOME:
182 kbinput = NANO_HOME_KEY;
183 break;
184 case KEY_BACKSPACE:
185 kbinput = NANO_BACKSPACE_KEY;
186 break;
187 case KEY_DC:
188 /* Terminal breakage, part 2: We should only get KEY_DC when
189 * hitting Delete, but we get it when hitting Backspace
190 * sometimes on FreeBSD. Thank you, Lee Nelson. */
191 kbinput = (rebind_delete) ? NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
192 break;
193 case KEY_IC:
194 kbinput = NANO_INSERTFILE_KEY;
195 break;
196 case KEY_NPAGE:
197 kbinput = NANO_NEXTPAGE_KEY;
198 break;
199 case KEY_PPAGE:
200 kbinput = NANO_PREVPAGE_KEY;
201 break;
202 case KEY_ENTER:
203 kbinput = NANO_ENTER_KEY;
204 break;
205 case KEY_END:
206 kbinput = NANO_END_KEY;
207 break;
208 case KEY_SUSPEND:
209 kbinput = NANO_SUSPEND_KEY;
210 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000211 }
212#ifdef DEBUG
213 fprintf(stderr, "get_accepted_kbinput(): kbinput = %d, meta = %d\n", kbinput, *meta);
214#endif
215 return kbinput;
216}
217
218/* Translate a three-digit decimal ASCII code from 000-255 into the
219 * corresponding ASCII character. */
220int get_ascii_kbinput(WINDOW *win, int kbinput)
221{
222 int retval;
223
224 switch (kbinput) {
225 case '0':
226 case '1':
227 case '2':
228 retval = (kbinput - 48) * 100;
229 break;
230 default:
231 return kbinput;
232 }
233
234 kbinput = wgetch(win);
235 switch (kbinput) {
236 case '0':
237 case '1':
238 case '2':
239 case '3':
240 case '4':
241 case '5':
242 retval += (kbinput - 48) * 10;
243 break;
244 case '6':
245 case '7':
246 case '8':
247 case '9':
248 if (retval < 200) {
249 retval += (kbinput - 48) * 10;
250 break;
251 }
252 default:
253 return kbinput;
254 }
255
256 kbinput = wgetch(win);
257 switch (kbinput) {
258 case '0':
259 case '1':
260 case '2':
261 case '3':
262 case '4':
263 case '5':
264 retval += kbinput - 48;
265 break;
266 case '6':
267 case '7':
268 case '8':
269 case '9':
270 if (retval < 250) {
271 retval += kbinput - 48;
272 break;
273 }
274 default:
275 return kbinput;
276 }
277
278#ifdef DEBUG
279 fprintf(stderr, "get_ascii_kbinput(): kbinput = %d\n", kbinput);
280#endif
281 return retval;
282}
283
284/* Translate common escape sequences for some keys. These are generated
285 * when the terminal doesn't support those keys. Assume nodelay(win) is
286 * TRUE. */
287int get_escape_seq_kbinput(WINDOW *win, int kbinput)
288{
289 switch (kbinput) {
290 case '3':
291 /* Esc [ 3 ~ == kdch1 on many terminals. */
292 kbinput = get_skip_tilde_kbinput(win, kbinput, NANO_DELETE_KEY);
293 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000294 }
295 return kbinput;
296}
297
298/* If there is no next character, return the passed-in error value. If
299 * the next character's a tilde, eat it and return the passed-in
300 * return value. Otherwise, return the next character. Assume
301 * nodelay(win) is TRUE. */
302int get_skip_tilde_kbinput(WINDOW *win, int errval, int retval)
303{
304 int kbinput = wgetch(win);
305 switch (kbinput) {
306 case ERR:
307 return errval;
308 case '~':
309 return retval;
310 default:
311 return kbinput;
312 }
313}
314
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000315int do_first_line(void)
316{
317 current = fileage;
318 placewewant = 0;
319 current_x = 0;
David Lawrence Ramseyd91ab6e2003-09-07 23:57:24 +0000320 edit_update(current, TOP);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000321 return 1;
322}
323
324int do_last_line(void)
325{
326 current = filebot;
327 placewewant = 0;
328 current_x = 0;
Chris Allegretta234a34d2000-07-29 04:33:38 +0000329 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000330 return 1;
331}
332
Chris Allegretta6df90f52002-07-19 01:08:59 +0000333/* Return the placewewant associated with current_x. That is, xplustabs
334 * is the zero-based column position of the cursor. Value is no smaller
335 * than current_x. */
336size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000337{
Chris Allegretta6df90f52002-07-19 01:08:59 +0000338 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000339}
340
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000341/* actual_x() gives the index in str of the character displayed at
342 * column xplus. That is, actual_x() is the largest value such that
343 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
344size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000345{
Chris Allegretta6df90f52002-07-19 01:08:59 +0000346 size_t i = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000347 /* the position in str, returned */
Chris Allegretta6df90f52002-07-19 01:08:59 +0000348 size_t length = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000349 /* the screen display width to str[i] */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000350
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000351 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000352
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000353 for (; length < xplus && *str != '\0'; i++, str++) {
354 if (*str == '\t')
Chris Allegretta6df90f52002-07-19 01:08:59 +0000355 length += tabsize - length % tabsize;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000356 else if (is_cntrl_char((int)*str))
Chris Allegretta6df90f52002-07-19 01:08:59 +0000357 length += 2;
Chris Allegretta6df90f52002-07-19 01:08:59 +0000358 else
359 length++;
360 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000361 assert(length == strnlenpt(str - i, i));
362 assert(i <= strlen(str - i));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000363
Chris Allegretta6df90f52002-07-19 01:08:59 +0000364 if (length > xplus)
365 i--;
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +0000366
Chris Allegretta6df90f52002-07-19 01:08:59 +0000367 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000368}
369
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +0000370/* A strlen with tabs factored in, similar to xplustabs(). How many
371 * columns wide are the first size characters of buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +0000372size_t strnlenpt(const char *buf, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +0000373{
Chris Allegretta6df90f52002-07-19 01:08:59 +0000374 size_t length = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000375
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +0000376 assert(buf != NULL);
377 for (; *buf != '\0' && size != 0; size--, buf++) {
378 if (*buf == '\t')
379 length += tabsize - (length % tabsize);
380 else if (is_cntrl_char((int)*buf))
381 length += 2;
382 else
383 length++;
384 }
Chris Allegretta6df90f52002-07-19 01:08:59 +0000385 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000386}
387
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +0000388/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +0000389size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +0000390{
Chris Allegretta6df90f52002-07-19 01:08:59 +0000391 return strnlenpt(buf, -1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +0000392}
393
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000394void blank_bottombars(void)
395{
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +0000396 if (!ISSET(NO_HELP)) {
Chris Allegretta6df90f52002-07-19 01:08:59 +0000397 mvwaddstr(bottomwin, 1, 0, hblank);
398 mvwaddstr(bottomwin, 2, 0, hblank);
399 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000400}
401
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000402void blank_bottomwin(void)
403{
404 if (ISSET(NO_HELP))
405 return;
406
407 mvwaddstr(bottomwin, 1, 0, hblank);
408 mvwaddstr(bottomwin, 2, 0, hblank);
409}
410
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000411void blank_edit(void)
412{
413 int i;
414 for (i = 0; i <= editwinrows - 1; i++)
415 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000416}
417
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000418void blank_statusbar(void)
419{
420 mvwaddstr(bottomwin, 0, 0, hblank);
421}
422
423void blank_statusbar_refresh(void)
424{
425 blank_statusbar();
426 wrefresh(bottomwin);
427}
428
429void check_statblank(void)
430{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000431 if (statblank > 1)
432 statblank--;
433 else if (statblank == 1 && !ISSET(CONSTUPDATE)) {
434 statblank--;
435 blank_statusbar_refresh();
436 }
437}
438
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000439/* Convert buf into a string that can be displayed on screen. The
440 * caller wants to display buf starting with column start_col, and
441 * extending for at most len columns. start_col is zero-based. len is
442 * one-based, so len == 0 means you get "" returned. The returned
443 * string is dynamically allocated, and should be freed. */
444char *display_string(const char *buf, size_t start_col, int len)
445{
446 size_t start_index;
447 /* Index in buf of first character shown in return value. */
448 size_t column;
449 /* Screen column start_index corresponds to. */
450 size_t end_index;
451 /* Index in buf of last character shown in return value. */
452 size_t alloc_len;
453 /* The length of memory allocated for converted. */
454 char *converted;
455 /* The string we return. */
456 size_t index;
457 /* Current position in converted. */
458
459 if (len == 0)
460 return mallocstrcpy(NULL, "");
461
462 start_index = actual_x(buf, start_col);
463 column = strnlenpt(buf, start_index);
464 assert(column <= start_col);
465 end_index = actual_x(buf, start_col + len - 1);
466 alloc_len = strnlenpt(buf, end_index + 1) - column;
467 if (len > alloc_len + column - start_col)
468 len = alloc_len + column - start_col;
469 converted = charalloc(alloc_len + 1);
470 buf += start_index;
471 index = 0;
472
473 for (; index < alloc_len; buf++) {
474 if (*buf == '\t')
475 do {
476 converted[index++] = ' ';
477 } while ((column + index) % tabsize);
478 else if (is_cntrl_char(*buf)) {
479 converted[index++] = '^';
480 if (*buf == '\n')
481 /* Treat newlines embedded in a line as encoded nulls;
482 * the line in question should be run through unsunder()
483 * before reaching here. */
484 converted[index++] = '@';
485 else if (*buf == NANO_CONTROL_8)
486 converted[index++] = '?';
487 else
488 converted[index++] = *buf + 64;
489 } else
490 converted[index++] = *buf;
491 }
492 assert(len <= alloc_len + column - start_col);
493 charmove(converted, converted + start_col - column, len);
494 null_at(&converted, len);
495
496 return charealloc(converted, len + 1);
497}
498
Chris Allegretta7662c862003-01-13 01:35:15 +0000499/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000500 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +0000501 *
Chris Allegretta7662c862003-01-13 01:35:15 +0000502 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +0000503 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000504void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000505{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000506 size_t x_real = strnlenpt(inputbuf, x);
507 int wid = COLS - strlen(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +0000508
Chris Allegretta6df90f52002-07-19 01:08:59 +0000509 assert(0 <= x && x <= strlen(inputbuf));
510
Chris Allegrettab3655b42001-10-22 03:15:31 +0000511 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000512 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000513
Chris Allegretta6df90f52002-07-19 01:08:59 +0000514 mvwaddstr(bottomwin, 0, 0, buf);
515 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000516
517 if (COLS > 1)
518 waddch(bottomwin, x_real < wid ? ' ' : '$');
519 if (COLS > 2) {
520 size_t page_start = x_real - x_real % wid;
521 char *expanded = display_string(inputbuf, page_start, wid);
522
523 assert(wid > 0);
524 assert(strlen(expanded) <= wid);
525 waddstr(bottomwin, expanded);
526 free(expanded);
527 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
528 } else
529 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +0000530 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000531}
532
Chris Allegretta6df90f52002-07-19 01:08:59 +0000533/* Get the input from the kb; this should only be called from
534 * statusq(). */
Chris Allegrettaf717f982003-02-13 22:25:01 +0000535int nanogetstr(int allowtabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +0000536#ifndef NANO_SMALL
537 historyheadtype *history_list,
538#endif
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000539 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +0000540#ifndef DISABLE_TABCOMP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000541 , int *list
Chris Allegrettabe77c612000-11-24 14:00:16 +0000542#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +0000543 )
Chris Allegretta6df90f52002-07-19 01:08:59 +0000544{
545 int kbinput;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000546 int meta;
Chris Allegretta09fc4302003-01-16 22:16:38 +0000547 static int x = -1;
Chris Allegretta6df90f52002-07-19 01:08:59 +0000548 /* the cursor position in 'answer' */
549 int xend;
550 /* length of 'answer', the status bar text */
551 int tabbed = 0;
552 /* used by input_tab() */
553 const shortcut *t;
Chris Allegretta598106e2002-01-19 01:59:37 +0000554
Chris Allegretta5beed502003-01-05 20:41:21 +0000555#ifndef NANO_SMALL
556 /* for history */
557 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +0000558 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +0000559 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000560 int last_kbinput = 0;
561
562 /* This variable is used in the search history code. use_cb == 0
563 means that we're using the existing history and ignoring
564 currentbuf. use_cb == 1 means that the entry in answer should be
565 moved to currentbuf or restored from currentbuf to answer.
566 use_cb == 2 means that the entry in currentbuf should be moved to
567 answer or restored from answer to currentbuf. */
568 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +0000569#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +0000570 xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +0000571
572 /* Only put x at the end of the string if it's uninitialized or if
573 it would be past the end of the string as it is. Otherwise,
574 leave it alone. This is so the cursor position stays at the same
575 place if a prompt-changing toggle is pressed. */
Chris Allegretta65f075d2003-02-13 03:03:49 +0000576 if (x == -1 || x > xend || resetstatuspos)
Chris Allegretta09fc4302003-01-16 22:16:38 +0000577 x = xend;
578
Chris Allegrettae1e0fd62003-04-15 01:15:09 +0000579 answer = charealloc(answer, xend + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000580 if (xend > 0)
581 strcpy(answer, def);
582 else
583 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000584
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000585#if !defined(DISABLE_HELP) || (!defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION))
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000586 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +0000587#endif
588
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000589 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +0000590
Chris Allegretta6df90f52002-07-19 01:08:59 +0000591 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000592
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000593 /* Make sure any editor screen updates are displayed before getting
594 input */
Chris Allegretta022b96f2000-11-14 17:47:58 +0000595 wrefresh(edit);
596
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000597 while ((kbinput = get_kbinput(bottomwin, &meta, ISSET(REBIND_DELETE))) != NANO_ENTER_KEY) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000598 for (t = s; t != NULL; t = t->next) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000599#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +0000600 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000601#endif
602
David Lawrence Ramsey7f47d422003-09-08 18:01:49 +0000603 if (kbinput == t->val && (kbinput < 32 || kbinput == 127)) {
Chris Allegretta5bf51d32000-11-16 06:01:10 +0000604
Chris Allegrettab3655b42001-10-22 03:15:31 +0000605#ifndef DISABLE_HELP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000606 /* Have to do this here, it would be too late to do it
607 in statusq() */
Chris Allegretta598106e2002-01-19 01:59:37 +0000608 if (kbinput == NANO_HELP_KEY || kbinput == NANO_HELP_FKEY) {
Chris Allegrettab3655b42001-10-22 03:15:31 +0000609 do_help();
610 break;
611 }
612#endif
Chris Allegretta5af58892003-01-17 21:07:38 +0000613
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000614 return t->val;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000615 }
616 }
Chris Allegretta6df90f52002-07-19 01:08:59 +0000617 assert(0 <= x && x <= xend && xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000618
Chris Allegretta04d848e2000-11-05 17:54:41 +0000619 if (kbinput != '\t')
620 tabbed = 0;
621
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000622 switch (kbinput) {
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000623#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000624 case KEY_MOUSE:
625 do_mouse();
626 break;
627#endif
Chris Allegretta658399a2001-06-14 02:54:22 +0000628 case NANO_HOME_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000629 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000630 break;
Chris Allegretta658399a2001-06-14 02:54:22 +0000631 case NANO_END_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000632 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000633 break;
Chris Allegretta35dac582001-03-21 15:07:20 +0000634 case NANO_FORWARD_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000635 if (x < xend)
636 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000637 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000638 case NANO_DELETE_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000639 if (x < xend) {
David Lawrence Ramsey9eff7462003-09-16 02:04:00 +0000640 charmove(answer + x, answer + x + 1, xend - x);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000641 xend--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000642 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000643 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000644 case NANO_CUT_KEY:
645 case NANO_UNCUT_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000646 null_at(&answer, 0);
647 xend = 0;
648 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000649 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000650 case NANO_BACKSPACE_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000651 if (x > 0) {
David Lawrence Ramsey9eff7462003-09-16 02:04:00 +0000652 charmove(answer + x - 1, answer + x, xend - x + 1);
Chris Allegretta04d848e2000-11-05 17:54:41 +0000653 x--;
Chris Allegretta6df90f52002-07-19 01:08:59 +0000654 xend--;
655 }
Chris Allegretta04d848e2000-11-05 17:54:41 +0000656 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000657 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +0000658#ifndef NANO_SMALL
659 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +0000660 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000661 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000662 history_list->current = (historytype *)history_list;
663 history_list->len = strlen(answer);
664 }
Chris Allegretta6df90f52002-07-19 01:08:59 +0000665
Chris Allegretta7662c862003-01-13 01:35:15 +0000666 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000667 complete = get_history_completion(history_list, answer);
668 xend = strlen(complete);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000669 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +0000670 answer = mallocstrcpy(answer, complete);
671 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000672 }
Chris Allegretta5beed502003-01-05 20:41:21 +0000673#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +0000674 else
675#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +0000676#endif
Chris Allegretta5beed502003-01-05 20:41:21 +0000677#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +0000678 if (allowtabs) {
679 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +0000680
Chris Allegretta327abda2003-01-17 05:04:17 +0000681 answer = input_tab(answer, x, &tabbed, &shift, list);
682 xend = strlen(answer);
683 x += shift;
684 if (x > xend)
685 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +0000686 }
687#endif
688 break;
Chris Allegretta35dac582001-03-21 15:07:20 +0000689 case NANO_BACK_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000690 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000691 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000692 break;
Chris Allegretta7662c862003-01-13 01:35:15 +0000693 case NANO_UP_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +0000694#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +0000695 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +0000696
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000697 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
698 isn't NULL, and currentbuf is different from answer,
699 it means that we're scrolling up at the top of the
700 search history, and we need to save the current
701 answer in currentbuf; do this and reset use_cb to
702 0 */
703 if (currentbuf == NULL || (use_cb == 1 && strcmp(currentbuf, answer))) {
Chris Allegretta8031f832003-01-09 05:29:58 +0000704 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000705 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +0000706 }
707
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000708 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
709 is different from answer, it means that we're
710 scrolling up at the bottom of the search history, and
711 we need to make the string in currentbuf the current
712 answer; do this, blow away currentbuf since we don't
713 need it anymore, and reset use_cb to 0 */
714 if (currentbuf != NULL && use_cb == 2 && strcmp(currentbuf, answer)) {
715 answer = mallocstrcpy(answer, currentbuf);
716 free(currentbuf);
717 currentbuf = NULL;
718 xend = strlen(answer);
719 use_cb = 0;
720
721 /* else get older search from the history list and save
722 it in answer; if there is no older search, blank out
723 answer */
724 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000725 answer = mallocstrcpy(answer, history);
726 xend = strlen(history);
727 } else {
728 answer = mallocstrcpy(answer, "");
729 xend = 0;
730 }
731 x = xend;
732 }
Chris Allegretta5beed502003-01-05 20:41:21 +0000733#endif
Chris Allegretta54abd942003-01-09 23:43:12 +0000734 break;
Chris Allegretta7662c862003-01-13 01:35:15 +0000735 case NANO_DOWN_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +0000736#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +0000737 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000738
739 /* get newer search from the history list and save it
740 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +0000741 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000742 answer = mallocstrcpy(answer, history);
743 xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +0000744
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000745 /* if there is no newer search, we're here */
746
747 /* if currentbuf isn't NULL and use_cb isn't 2, it means
748 that we're scrolling down at the bottom of the search
749 history and we need to make the string in currentbuf
750 the current answer; do this, blow away currentbuf
751 since we don't need it anymore, and set use_cb to
752 1 */
753 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +0000754 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +0000755 free(currentbuf);
756 currentbuf = NULL;
757 xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000758 use_cb = 1;
759
760 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
761 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +0000762 the search history and the current answer (if it's
763 not blank) needs to be saved in currentbuf; do this,
764 blank out answer (if necessary), and set use_cb to
765 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000766 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +0000767 if (answer[0] != '\0') {
768 currentbuf = mallocstrcpy(currentbuf, answer);
769 answer = mallocstrcpy(answer, "");
770 }
Chris Allegretta5beed502003-01-05 20:41:21 +0000771 xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000772 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +0000773 }
774 x = xend;
775 }
776#endif
777 break;
Chris Allegretta658399a2001-06-14 02:54:22 +0000778 default:
779
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000780 for (t = s; t != NULL; t = t->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +0000781#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +0000782 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
Chris Allegretta598106e2002-01-19 01:59:37 +0000783 kbinput);
Chris Allegretta658399a2001-06-14 02:54:22 +0000784#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000785 if (meta == 1 && (kbinput == t->val || kbinput == t->val - 32))
Chris Allegretta5af58892003-01-17 21:07:38 +0000786 /* We hit an Alt key. Do like above. We don't
787 just ungetch() the letter and let it get
788 caught above cause that screws the
789 keypad... */
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000790 return t->val;
Chris Allegretta658399a2001-06-14 02:54:22 +0000791 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000792
David Lawrence Ramsey7f47d422003-09-08 18:01:49 +0000793 if (kbinput < 32 || kbinput == 127)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000794 break;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000795 answer = charealloc(answer, xend + 2);
David Lawrence Ramsey9eff7462003-09-16 02:04:00 +0000796 charmove(answer + x + 1, answer + x, xend - x + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000797 xend++;
798 answer[x] = kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000799 x++;
800
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000801#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +0000802 fprintf(stderr, "input \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000803#endif
Chris Allegretta5beed502003-01-05 20:41:21 +0000804 } /* switch (kbinput) */
Chris Allegrettaa65ba512003-01-05 20:57:07 +0000805#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +0000806 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +0000807#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +0000808 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000809 wrefresh(bottomwin);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000810 } /* while (kbinput ...) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000811
Chris Allegretta5af58892003-01-17 21:07:38 +0000812 /* We finished putting in an answer; reset x */
813 x = -1;
814
Chris Allegretta7662c862003-01-13 01:35:15 +0000815 /* Just check for a blank answer here */
Chris Allegretta15c28f82003-01-05 21:47:06 +0000816 if (answer[0] == '\0')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000817 return -2;
818 else
819 return 0;
820}
821
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000822/* If modified is not already set, set it and update titlebar. */
823void set_modified(void)
824{
825 if (!ISSET(MODIFIED)) {
826 SET(MODIFIED);
827 titlebar(NULL);
828 wrefresh(topwin);
829 }
830}
831
Chris Allegrettaf717f982003-02-13 22:25:01 +0000832void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000833{
834 int namelen, space;
Chris Allegrettaf717f982003-02-13 22:25:01 +0000835 const char *what = path;
Chris Allegrettaf4b96012001-01-03 07:11:47 +0000836
837 if (path == NULL)
838 what = filename;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000839
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000840 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +0000841
Chris Allegretta6df90f52002-07-19 01:08:59 +0000842 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyc5967552002-06-21 03:20:06 +0000843 mvwaddnstr(topwin, 0, 2, VERMSG, COLS - 3);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000844
David Lawrence Ramseyec290f22003-08-30 19:05:40 +0000845 space = COLS - sizeof(VERMSG) - 23;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000846
Chris Allegrettaf4b96012001-01-03 07:11:47 +0000847 namelen = strlen(what);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000848
David Lawrence Ramseyc5967552002-06-21 03:20:06 +0000849 if (space > 0) {
850 if (what[0] == '\0')
Chris Allegretta6df90f52002-07-19 01:08:59 +0000851 mvwaddnstr(topwin, 0, COLS / 2 - 6, _("New Buffer"),
852 COLS / 2 + COLS % 2 - 6);
853 else if (namelen > space) {
854 if (path == NULL)
855 waddstr(topwin, _(" File: ..."));
856 else
857 waddstr(topwin, _(" DIR: ..."));
858 waddstr(topwin, &what[namelen - space]);
859 } else {
860 if (path == NULL)
861 mvwaddstr(topwin, 0, COLS / 2 - (namelen / 2 + 1),
862 _("File: "));
863 else
864 mvwaddstr(topwin, 0, COLS / 2 - (namelen / 2 + 1),
865 _(" DIR: "));
866 waddstr(topwin, what);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000867 }
David Lawrence Ramseyc5967552002-06-21 03:20:06 +0000868 } /* If we don't have space, we shouldn't bother */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000869 if (ISSET(MODIFIED))
Chris Allegretta6df90f52002-07-19 01:08:59 +0000870 mvwaddnstr(topwin, 0, COLS - 11, _(" Modified "), 11);
Chris Allegretta4dc03d52002-05-11 03:04:44 +0000871 else if (ISSET(VIEW_MODE))
Chris Allegretta6df90f52002-07-19 01:08:59 +0000872 mvwaddnstr(topwin, 0, COLS - 11, _(" View "), 11);
Chris Allegretta8ce24132001-04-30 11:28:46 +0000873
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000874 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +0000875
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000876 wrefresh(topwin);
877 reset_cursor();
878}
879
Chris Allegretta6232d662002-05-12 19:52:15 +0000880void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000881{
Chris Allegrettabc72e362002-02-16 20:03:44 +0000882 int i, j, numcols;
Chris Allegretta3bbc4162003-01-23 00:46:12 +0000883 char keystr[9];
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000884 int slen;
885
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000886 if (ISSET(NO_HELP))
887 return;
888
Chris Allegretta6232d662002-05-12 19:52:15 +0000889 if (s == main_list) {
890 slen = MAIN_VISIBLE;
891 assert(MAIN_VISIBLE <= length_of_list(s));
892 } else
893 slen = length_of_list(s);
894
Chris Allegretta6232d662002-05-12 19:52:15 +0000895 /* There will be this many columns of shortcuts */
896 numcols = (slen + (slen % 2)) / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000897
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000898 blank_bottomwin();
Chris Allegretta658399a2001-06-14 02:54:22 +0000899
Chris Allegrettabc72e362002-02-16 20:03:44 +0000900 for (i = 0; i < numcols; i++) {
901 for (j = 0; j <= 1; j++) {
Chris Allegretta658399a2001-06-14 02:54:22 +0000902
Chris Allegretta6232d662002-05-12 19:52:15 +0000903 wmove(bottomwin, 1 + j, i * (COLS / numcols));
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000904
Chris Allegretta5beed502003-01-05 20:41:21 +0000905 /* Yucky sentinel values we can't handle a better way */
Chris Allegretta6232d662002-05-12 19:52:15 +0000906 if (s->val == NANO_CONTROL_SPACE)
907 strcpy(keystr, "^ ");
Chris Allegrettaa65ba512003-01-05 20:57:07 +0000908#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +0000909 else if (s->val == KEY_UP)
Chris Allegretta3bbc4162003-01-23 00:46:12 +0000910 strncpy(keystr, _("Up"), 8);
Chris Allegretta5beed502003-01-05 20:41:21 +0000911#endif /* NANO_SMALL */
912 else if (s->val > 0) {
Chris Allegretta6232d662002-05-12 19:52:15 +0000913 if (s->val < 64)
914 sprintf(keystr, "^%c", s->val + 64);
915 else
916 sprintf(keystr, "M-%c", s->val - 32);
917 } else if (s->altval > 0)
918 sprintf(keystr, "M-%c", s->altval);
Chris Allegretta658399a2001-06-14 02:54:22 +0000919
Chris Allegretta6232d662002-05-12 19:52:15 +0000920 onekey(keystr, s->desc, COLS / numcols);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000921
Chris Allegretta6232d662002-05-12 19:52:15 +0000922 s = s->next;
923 if (s == NULL)
924 goto break_completely_out;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000925 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000926 }
927
Chris Allegretta6df90f52002-07-19 01:08:59 +0000928 break_completely_out:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000929 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000930}
931
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000932/* Write a shortcut key to the help area at the bottom of the window.
933 * keystroke is e.g. "^G" and desc is e.g. "Get Help".
934 * We are careful to write exactly len characters, even if len is
935 * very small and keystroke and desc are long. */
Chris Allegrettaf717f982003-02-13 22:25:01 +0000936void onekey(const char *keystroke, const char *desc, int len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000937{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000938 wattron(bottomwin, A_REVERSE);
939 waddnstr(bottomwin, keystroke, len);
940 wattroff(bottomwin, A_REVERSE);
941 len -= strlen(keystroke);
942 if (len > 0) {
943 waddch(bottomwin, ' ');
944 len--;
945 waddnstr(bottomwin, desc, len);
946 len -= strlen(desc);
947 for (; len > 0; len--)
948 waddch(bottomwin, ' ');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000949 }
950}
951
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000952/* And so start the display update routines. */
953
954#ifndef NDEBUG
955int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000956{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000957 int check_line = 0;
958 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000959
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000960 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
961 check_line++;
962 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000963}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000964#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +0000965
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000966 /* nano scrolls horizontally within a line in chunks. This function
967 * returns the column number of the first character displayed in the
968 * window when the cursor is at the given column. */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000969int get_page_start(int column)
Chris Allegretta6df90f52002-07-19 01:08:59 +0000970{
971 assert(COLS > 9);
972 return column < COLS - 1 ? 0 : column - 7 - (column - 8) % (COLS - 9);
973}
974
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000975/* Resets current_y, based on the position of current, and puts the
976 * cursor at (current_y, current_x). */
977void reset_cursor(void)
978{
979 const filestruct *ptr = edittop;
980 size_t x;
981
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000982 /* Yuck. This condition can be true after open_file() when opening
983 * the first file. */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000984 if (edittop == NULL)
985 return;
986
987 current_y = 0;
988
989 while (ptr != current && ptr != editbot && ptr->next != NULL) {
990 ptr = ptr->next;
991 current_y++;
992 }
993
994 x = xplustabs();
995 wmove(edit, current_y, x - get_page_start(x));
996}
Chris Allegretta6df90f52002-07-19 01:08:59 +0000997
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +0000998/* edit_add() takes care of the job of actually painting a line into the
999 * edit window. fileptr is the line to be painted, at row yval of the
1000 * window. converted is the actual string to be written to the window,
1001 * with tabs and control characters replaced by strings of regular
1002 * characters. start is the column number of the first character
1003 * of this page. That is, the first character of converted corresponds to
1004 * character number actual_x(fileptr->data, start) of the line. */
1005void edit_add(const filestruct *fileptr, const char *converted,
1006 int yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001007{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001008#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
1009 size_t startpos = actual_x(fileptr->data, start);
1010 /* The position in fileptr->data of the leftmost character
1011 * that displays at least partially on the window. */
1012 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
1013 /* The position in fileptr->data of the first character that is
1014 * completely off the window to the right.
1015 *
1016 * Note that endpos might be beyond the null terminator of the
1017 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00001018#endif
1019
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001020 assert(fileptr != NULL && converted != NULL);
1021 assert(strlen(converted) <= COLS);
1022
Chris Allegretta2fa11b82001-12-02 04:55:44 +00001023 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001024 * just the text that needs it). */
1025 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00001026
Chris Allegretta7dd77682001-12-08 19:52:28 +00001027#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00001028 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001029 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00001030
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001031 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
1032 int x_start;
1033 /* Starting column for mvwaddnstr. Zero-based. */
1034 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001035 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001036 * characters on a whole line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001037 regmatch_t startmatch; /* match position for start_regexp */
1038 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001039
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001040 if (tmpcolor->bright)
1041 wattron(edit, A_BOLD);
1042 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001043 /* Two notes about regexec(). Return value 0 means there is
1044 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001045 * after the match. */
1046
1047 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001048 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001049 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00001050
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001051 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001052 * last match. Even though two matches may overlap, we
1053 * want to ignore them, so that we can highlight
1054 * C-strings correctly. */
1055 while (k < endpos) {
1056 /* Note the fifth parameter to regexec(). It says
1057 * not to match the beginning-of-line character
1058 * unless k is 0. If regexec() returns REG_NOMATCH,
1059 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00001060 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001061 &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001062 break;
1063 /* Translate the match to the beginning of the line. */
1064 startmatch.rm_so += k;
1065 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00001066 if (startmatch.rm_so == startmatch.rm_eo) {
1067 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00001068 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001069 } else if (startmatch.rm_so < endpos &&
1070 startmatch.rm_eo > startpos) {
1071 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001072 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001073 else
1074 x_start = strnlenpt(fileptr->data, startmatch.rm_so)
1075 - start;
1076 paintlen = strnlenpt(fileptr->data, startmatch.rm_eo)
1077 - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001078 if (paintlen > COLS - x_start)
1079 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001080
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001081 assert(0 <= x_start && 0 < paintlen &&
1082 x_start + paintlen <= COLS);
1083 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001084 converted + x_start, paintlen);
1085 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001086 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00001087 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001088 } else {
1089 /* This is a multi-line regexp. There are two steps.
1090 * First, we have to see if the beginning of the line is
1091 * colored by a start on an earlier line, and an end on
1092 * this line or later.
1093 *
1094 * We find the first line before fileptr matching the
1095 * start. If every match on that line is followed by an
1096 * end, then go to step two. Otherwise, find the next line
1097 * after start_line matching the end. If that line is not
1098 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +00001099
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001100 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001101 /* the first line before fileptr matching start */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001102 regoff_t start_col;
1103 /* where it starts in that line */
1104 const filestruct *end_line;
1105 int searched_later_lines = 0;
1106 /* Used in step 2. Have we looked for an end on
1107 * lines after fileptr? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001108
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001109 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00001110 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001111 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001112 /* If there is an end on this line, there is no need
1113 * to look for starts on earlier lines. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001114 if (regexec(tmpcolor->end, start_line->data, 0, NULL, 0)
1115 == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001116 goto step_two;
1117 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001118 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001119 /* No start found, so skip to the next step. */
1120 if (start_line == NULL)
1121 goto step_two;
1122 /* Now start_line is the first line before fileptr
1123 * containing a start match. Is there a start on this
1124 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001125
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001126 start_col = 0;
1127 while (1) {
1128 start_col += startmatch.rm_so;
1129 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001130 if (regexec(tmpcolor->end,
1131 start_line->data + start_col + startmatch.rm_eo,
1132 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
1133 REG_NOTBOL) == REG_NOMATCH)
1134 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001135 break;
1136 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +00001137 if (regexec(&tmpcolor->start,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001138 start_line->data + start_col, 1, &startmatch,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001139 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001140 /* No later start on this line. */
1141 goto step_two;
1142 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001143 /* Indeed, there is a start not followed on this line by
1144 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001145
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001146 /* We have already checked that there is no end before
1147 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001148 * the start at all? We don't paint unterminated
1149 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001150 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00001151 while (end_line != NULL &&
1152 regexec(tmpcolor->end, end_line->data, 1, &endmatch, 0))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001153 end_line = end_line->next;
1154
1155 /* No end found, or it is too early. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001156 if (end_line == NULL ||
1157 (end_line == fileptr && endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001158 goto step_two;
1159
1160 /* Now paint the start of fileptr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001161 paintlen = end_line != fileptr ? COLS :
1162 strnlenpt(fileptr->data, endmatch.rm_eo) - start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001163 if (paintlen > COLS)
1164 paintlen = COLS;
1165
1166 assert(0 < paintlen && paintlen <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001167 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001168
1169 /* We have already painted the whole line. */
1170 if (paintlen == COLS)
1171 goto skip_step_two;
1172
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001173 step_two: /* Second step, we look for starts on this line. */
1174 start_col = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001175 while (start_col < endpos) {
Chris Allegrettace452fb2003-02-03 02:56:44 +00001176 if (regexec(&tmpcolor->start, fileptr->data + start_col, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001177 &startmatch, start_col == 0 ? 0 : REG_NOTBOL)
1178 == REG_NOMATCH || start_col + startmatch.rm_so >=
1179 endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001180 /* No more starts on this line. */
1181 break;
1182 /* Translate the match to be relative to the
1183 * beginning of the line. */
1184 startmatch.rm_so += start_col;
1185 startmatch.rm_eo += start_col;
1186
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001187 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001188 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001189 else
1190 x_start = strnlenpt(fileptr->data, startmatch.rm_so)
1191 - start;
1192 if (regexec(tmpcolor->end, fileptr->data + startmatch.rm_eo,
1193 1, &endmatch, startmatch.rm_eo == 0 ? 0 :
1194 REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001195 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001196 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001197 endmatch.rm_so += startmatch.rm_eo;
1198 endmatch.rm_eo += startmatch.rm_eo;
1199 /* There is an end on this line. But does it
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001200 * appear on this page, and is the match more than
1201 * zero characters long? */
1202 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001203 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001204 paintlen = strnlenpt(fileptr->data, endmatch.rm_eo)
1205 - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001206 if (x_start + paintlen > COLS)
1207 paintlen = COLS - x_start;
1208
1209 assert(0 <= x_start && 0 < paintlen &&
1210 x_start + paintlen <= COLS);
1211 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001212 converted + x_start, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001213 }
1214 } else if (!searched_later_lines) {
1215 searched_later_lines = 1;
1216 /* There is no end on this line. But we haven't
1217 * yet looked for one on later lines. */
1218 end_line = fileptr->next;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001219 while (end_line != NULL &&
1220 regexec(tmpcolor->end, end_line->data, 0,
1221 NULL, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001222 end_line = end_line->next;
1223 if (end_line != NULL) {
1224 assert(0 <= x_start && x_start < COLS);
1225 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001226 converted + x_start,
1227 COLS - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001228 /* We painted to the end of the line, so
1229 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001230 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00001231 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001232 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001233 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001234 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001235 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00001236
Chris Allegrettace452fb2003-02-03 02:56:44 +00001237 skip_step_two:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001238 wattroff(edit, A_BOLD);
1239 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
1240 } /* for tmpcolor in colorstrings */
1241 }
Chris Allegretta598106e2002-01-19 01:59:37 +00001242#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001243
Chris Allegretta7dd77682001-12-08 19:52:28 +00001244#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001245 if (ISSET(MARK_ISSET)
1246 && (fileptr->lineno <= mark_beginbuf->lineno
1247 || fileptr->lineno <= current->lineno)
1248 && (fileptr->lineno >= mark_beginbuf->lineno
1249 || fileptr->lineno >= current->lineno)) {
1250 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00001251
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001252 const filestruct *top;
1253 /* Either current or mark_beginbuf, whichever is first. */
1254 size_t top_x;
1255 /* current_x or mark_beginx, corresponding to top. */
1256 const filestruct *bot;
1257 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001258 int x_start;
1259 /* Starting column for mvwaddnstr. Zero-based. */
1260 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001261 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001262 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001263
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001264 mark_order(&top, &top_x, &bot, &bot_x);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001265
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001266 if (top->lineno < fileptr->lineno || top_x < startpos)
1267 top_x = startpos;
1268 if (bot->lineno > fileptr->lineno || bot_x > endpos)
1269 bot_x = endpos;
1270
1271 /* the selected bit of fileptr is on this page */
1272 if (top_x < endpos && bot_x > startpos) {
1273 assert(startpos <= top_x);
1274 x_start = strnlenpt(fileptr->data + startpos, top_x - startpos);
1275
1276 if (bot_x >= endpos)
1277 paintlen = -1; /* Paint everything. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001278 else
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001279 paintlen = strnlenpt(fileptr->data + top_x, bot_x - top_x);
1280
1281 assert(x_start >= 0 && x_start <= strlen(converted));
1282
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001283 wattron(edit, A_REVERSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001284 mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001285 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001286 }
Chris Allegretta08893e02001-11-29 02:42:27 +00001287 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001288#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001289}
1290
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001291/* Just update one line in the edit buffer. Basically a wrapper for
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001292 * edit_add().
1293 *
1294 * If fileptr != current, then index is considered 0.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001295 * The line will be displayed starting with fileptr->data[index].
1296 * Likely args are current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001297void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001298{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001299 int line;
1300 /* line in the edit window for CURSES calls */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001301 char *converted;
1302 /* fileptr->data converted to have tabs and control characters
1303 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001304 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001305
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001306 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00001307
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001308 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001309
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001310 /* We assume the line numbers are valid. Is that really true? */
1311 assert(line < 0 || line == check_linenumbers(fileptr));
1312
1313 if (line < 0 || line >= editwinrows)
1314 return;
1315
1316 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001317 mvwaddstr(edit, line, 0, hblank);
1318
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001319 /* Next, convert variables that index the line to their equivalent
1320 * positions in the expanded line. */
1321 index = fileptr == current ? strnlenpt(fileptr->data, index) : 0;
1322 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00001323
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001324 /* Expand the line, replacing Tab by spaces, and control characters
1325 * by their display form. */
1326 converted = display_string(fileptr->data, page_start, COLS);
Robert Siemborski53875912000-06-16 04:25:30 +00001327
Chris Allegretta4dc03d52002-05-11 03:04:44 +00001328 /* Now, paint the line */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001329 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001330 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001331
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001332 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001333 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001334 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001335 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001336}
1337
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001338/* This function updates current, based on where current_y is;
1339 * reset_cursor() does the opposite. */
1340void update_cursor(void)
1341{
1342 int i = 0;
1343
1344#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001345 fprintf(stderr, "Moved to (%d, %d) in edit buffer\n", current_y,
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001346 current_x);
1347#endif
1348
1349 current = edittop;
1350 while (i < current_y && current->next != NULL) {
1351 current = current->next;
1352 i++;
1353 }
1354
1355#ifdef DEBUG
Chris Allegretta0e86e602003-01-23 04:27:23 +00001356 fprintf(stderr, "current->data = \"%s\"\n", current->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001357#endif
1358}
1359
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001360void center_cursor(void)
1361{
1362 current_y = editwinrows / 2;
1363 wmove(edit, current_y, current_x);
1364}
1365
Chris Allegretta6df90f52002-07-19 01:08:59 +00001366/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001367void edit_refresh(void)
1368{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001369 /* Neither of these conditions should occur, but they do. edittop
1370 * is NULL when you open an existing file on the command line, and
Chris Allegretta6df90f52002-07-19 01:08:59 +00001371 * ENABLE_COLOR is defined. Yuck. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001372 if (current == NULL)
1373 return;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001374 if (edittop == NULL)
1375 edittop = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001376
Chris Allegretta63d0b482003-01-26 19:47:10 +00001377 if (current->lineno < edittop->lineno ||
1378 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001379 /* Note that edit_update() changes edittop so that
1380 * current->lineno = edittop->lineno + editwinrows / 2. Thus
1381 * when it then calls edit_refresh(), there is no danger of
1382 * getting an infinite loop. */
Chris Allegrettada721be2000-07-31 01:26:42 +00001383 edit_update(current, CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001384 else {
1385 int nlines = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001386
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001387 /* Don't make the cursor jump around the screen whilst
1388 * updating. */
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001389 leaveok(edit, TRUE);
1390
1391 editbot = edittop;
1392 while (nlines < editwinrows) {
1393 update_line(editbot, current_x);
1394 nlines++;
1395 if (editbot->next == NULL)
1396 break;
1397 editbot = editbot->next;
1398 }
1399 while (nlines < editwinrows) {
1400 mvwaddstr(edit, nlines, 0, hblank);
1401 nlines++;
1402 }
1403 /* What the hell are we expecting to update the screen if this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001404 * isn't here? Luck? */
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001405 wrefresh(edit);
1406 leaveok(edit, FALSE);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001407 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001408}
1409
Chris Allegretta7662c862003-01-13 01:35:15 +00001410/* Same as above, but touch the window first, so everything is
1411 * redrawn. */
Chris Allegrettaf1d33d32000-08-19 03:53:39 +00001412void edit_refresh_clearok(void)
1413{
1414 clearok(edit, TRUE);
1415 edit_refresh();
1416 clearok(edit, FALSE);
1417}
1418
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001419/* Nice generic routine to update the edit buffer, given a pointer to the
1420 * file struct =) */
David Lawrence Ramsey1356a0a2003-09-10 20:31:02 +00001421void edit_update(filestruct *fileptr, topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001422{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001423 if (fileptr == NULL)
1424 return;
1425
Chris Allegretta6df90f52002-07-19 01:08:59 +00001426 if (location != TOP) {
David Lawrence Ramseyd91ab6e2003-09-07 23:57:24 +00001427 int goal = location == NONE ? current_y : editwinrows / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001428
David Lawrence Ramseyd91ab6e2003-09-07 23:57:24 +00001429 for (; goal > 0 && fileptr->prev != NULL; goal--)
Chris Allegretta6df90f52002-07-19 01:08:59 +00001430 fileptr = fileptr->prev;
1431 }
1432 edittop = fileptr;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001433 edit_refresh();
1434}
1435
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001436/* Ask a question on the statusbar. Answer will be stored in answer
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001437 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
Chris Allegretta88520c92001-05-05 17:45:54 +00001438 * otherwise, the valid shortcut key caught. Def is any editable text we
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001439 * want to put up by default.
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00001440 *
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001441 * New arg tabs tells whether or not to allow tab completion. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001442int statusq(int tabs, const shortcut *s, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00001443#ifndef NANO_SMALL
1444 historyheadtype *which_history,
1445#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001446 const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001447{
1448 va_list ap;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001449 char *foo = charalloc(COLS - 3);
Chris Allegretta9caa1932002-02-15 20:08:05 +00001450 int ret;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001451#ifndef DISABLE_TABCOMP
Chris Allegrettaa16e4e92002-01-05 18:59:54 +00001452 int list = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001453#endif
1454
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001455 bottombars(s);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001456
1457 va_start(ap, msg);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001458 vsnprintf(foo, COLS - 4, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001459 va_end(ap);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001460 foo[COLS - 4] = '\0';
Chris Allegretta8ce24132001-04-30 11:28:46 +00001461
Chris Allegretta5beed502003-01-05 20:41:21 +00001462 ret = nanogetstr(tabs, foo, def,
1463#ifndef NANO_SMALL
1464 which_history,
Chris Allegretta2084acc2001-11-29 03:43:08 +00001465#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00001466 s
1467#ifndef DISABLE_TABCOMP
1468 , &list
1469#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00001470 );
Chris Allegretta6df90f52002-07-19 01:08:59 +00001471 free(foo);
Chris Allegretta65f075d2003-02-13 03:03:49 +00001472 resetstatuspos = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001473
1474 switch (ret) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001475 case NANO_FIRSTLINE_KEY:
1476 do_first_line();
Chris Allegretta65f075d2003-02-13 03:03:49 +00001477 resetstatuspos = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001478 break;
1479 case NANO_LASTLINE_KEY:
1480 do_last_line();
Chris Allegretta65f075d2003-02-13 03:03:49 +00001481 resetstatuspos = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001482 break;
David Lawrence Ramsey8faf3052003-09-04 20:25:29 +00001483#ifndef DISABLE_JUSTIFY
1484 case NANO_PARABEGIN_KEY:
1485 do_para_begin();
1486 resetstatuspos = 1;
1487 break;
1488 case NANO_PARAEND_KEY:
1489 do_para_end();
1490 resetstatuspos = 1;
1491 break;
1492#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001493 case NANO_CANCEL_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001494 ret = -1;
Chris Allegretta65f075d2003-02-13 03:03:49 +00001495 resetstatuspos = 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001496 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001497 }
Chris Allegrettaa90d0cf2003-02-10 02:55:03 +00001498 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001499
1500#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001501 fprintf(stderr, "I got \"%s\"\n", answer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001502#endif
1503
Chris Allegretta6df90f52002-07-19 01:08:59 +00001504#ifndef DISABLE_TABCOMP
1505 /* if we've done tab completion, there might be a list of
1506 filename matches on the edit window at this point; make sure
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001507 they're cleared off. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001508 if (list)
1509 edit_refresh();
1510#endif
1511
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001512 return ret;
1513}
1514
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001515/* Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001516 * for N, 2 for All (if all is nonzero when passed in) and -1 for abort
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001517 * (^C). */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001518int do_yesno(int all, int leavecursor, const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001519{
1520 va_list ap;
Chris Allegrettadb28e962003-01-28 01:23:40 +00001521 char *foo;
1522 int ok = -2;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001523 const char *yesstr; /* String of yes characters accepted */
1524 const char *nostr; /* Same for no */
1525 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00001526
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001527 /* Yes, no and all are strings of any length. Each string consists
1528 * of all characters accepted as a valid character for that value.
1529 * The first value will be the one displayed in the shortcuts. */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001530 yesstr = _("Yy");
1531 nostr = _("Nn");
1532 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001533
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001534 /* Remove gettext call for keybindings until we clear the thing
1535 * up. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001536 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001537 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00001538
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001539 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00001540 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001541
Chris Allegretta6232d662002-05-12 19:52:15 +00001542 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00001543 wmove(bottomwin, 1, 0);
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001544 onekey(shortstr, _("Yes"), 16);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001545
1546 if (all) {
Chris Allegrettadb28e962003-01-28 01:23:40 +00001547 wmove(bottomwin, 1, 16);
Chris Allegretta6232d662002-05-12 19:52:15 +00001548 shortstr[1] = allstr[0];
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001549 onekey(shortstr, _("All"), 16);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001550 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001551
Chris Allegrettadb28e962003-01-28 01:23:40 +00001552 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00001553 shortstr[1] = nostr[0];
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001554 onekey(shortstr, _("No"), 16);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001555
Chris Allegrettadb28e962003-01-28 01:23:40 +00001556 wmove(bottomwin, 2, 16);
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001557 onekey("^C", _("Cancel"), 16);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001558 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00001559
1560 foo = charalloc(COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001561 va_start(ap, msg);
Chris Allegrettadb28e962003-01-28 01:23:40 +00001562 vsnprintf(foo, COLS, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001563 va_end(ap);
Chris Allegrettadb28e962003-01-28 01:23:40 +00001564 foo[COLS - 1] = '\0';
Chris Allegretta8ce24132001-04-30 11:28:46 +00001565
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001566 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001567
1568 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001569 mvwaddstr(bottomwin, 0, 0, foo);
Chris Allegrettadb28e962003-01-28 01:23:40 +00001570 free(foo);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001571
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001572 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001573
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001574 wrefresh(bottomwin);
1575
Chris Allegrettadb28e962003-01-28 01:23:40 +00001576 do {
1577 int kbinput = wgetch(edit);
Chris Allegrettab2cd2482003-02-12 23:18:19 +00001578#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegrettadb28e962003-01-28 01:23:40 +00001579 MEVENT mevent;
Chris Allegretta235ab192001-04-12 13:24:40 +00001580#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001581
Chris Allegrettadb28e962003-01-28 01:23:40 +00001582 if (kbinput == NANO_CONTROL_C)
1583 ok = -1;
Chris Allegrettab2cd2482003-02-12 23:18:19 +00001584#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegrettadb28e962003-01-28 01:23:40 +00001585 /* Look ma! We get to duplicate lots of code from do_mouse!! */
1586 else if (kbinput == KEY_MOUSE && getmouse(&mevent) != ERR &&
1587 wenclose(bottomwin, mevent.y, mevent.x) &&
1588 !ISSET(NO_HELP) && mevent.x < 32 &&
1589 mevent.y >= editwinrows + 3) {
1590 int x = mevent.x /= 16;
1591 /* Did we click in the first column of shortcuts, or the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001592 * second? */
Chris Allegrettadb28e962003-01-28 01:23:40 +00001593 int y = mevent.y - editwinrows - 3;
1594 /* Did we click in the first row of shortcuts? */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001595
Chris Allegrettadb28e962003-01-28 01:23:40 +00001596 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
1597 /* x = 0 means they clicked Yes or No.
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001598 * y = 0 means Yes or All. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00001599 ok = -2 * x * y + x - y + 1;
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001600
Chris Allegrettadb28e962003-01-28 01:23:40 +00001601 if (ok == 2 && !all)
1602 ok = -2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001603 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00001604#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001605 /* Look for the kbinput in the yes, no and (optionally) all
1606 * str. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00001607 else if (strchr(yesstr, kbinput) != NULL)
1608 ok = 1;
1609 else if (strchr(nostr, kbinput) != NULL)
1610 ok = 0;
1611 else if (all && strchr(allstr, kbinput) != NULL)
1612 ok = 2;
1613 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001614
Chris Allegrettadb28e962003-01-28 01:23:40 +00001615 /* Then blank the statusbar. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001616 blank_statusbar_refresh();
1617
Chris Allegrettadb28e962003-01-28 01:23:40 +00001618 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001619}
1620
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001621int total_refresh(void)
1622{
1623 clearok(edit, TRUE);
1624 clearok(topwin, TRUE);
1625 clearok(bottomwin, TRUE);
1626 wnoutrefresh(edit);
1627 wnoutrefresh(topwin);
1628 wnoutrefresh(bottomwin);
1629 doupdate();
1630 clearok(edit, FALSE);
1631 clearok(topwin, FALSE);
1632 clearok(bottomwin, FALSE);
1633 edit_refresh();
1634 titlebar(NULL);
1635 return 1;
1636}
1637
1638void display_main_list(void)
1639{
1640 bottombars(main_list);
1641}
1642
Chris Allegretta6df90f52002-07-19 01:08:59 +00001643void statusbar(const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001644{
1645 va_list ap;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001646
Chris Allegrettaa0d89972003-02-03 03:32:08 +00001647 va_start(ap, msg);
1648
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001649 /* Curses mode is turned off. If we use wmove() now, it will muck
1650 * up the terminal settings. So we just use vfprintf(). */
Chris Allegrettaa0d89972003-02-03 03:32:08 +00001651 if (curses_ended) {
1652 vfprintf(stderr, msg, ap);
1653 va_end(ap);
1654 return;
1655 }
1656
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001657 /* Blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001658 blank_statusbar();
1659
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001660 if (COLS >= 4) {
1661 char *bar;
1662 char *foo;
1663 int start_x = 0;
1664 size_t foo_len;
1665 bar = charalloc(COLS - 3);
1666 vsnprintf(bar, COLS - 3, msg, ap);
1667 va_end(ap);
1668 foo = display_string(bar, 0, COLS - 4);
1669 free(bar);
1670 foo_len = strlen(foo);
1671 start_x = (COLS - foo_len - 4) / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001672
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001673 wmove(bottomwin, 0, start_x);
1674 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001675
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001676 waddstr(bottomwin, "[ ");
1677 waddstr(bottomwin, foo);
1678 free(foo);
1679 waddstr(bottomwin, " ]");
1680 wattroff(bottomwin, A_REVERSE);
1681 wnoutrefresh(bottomwin);
1682 wrefresh(edit);
1683 /* Leave the cursor at its position in the edit window, not
1684 * in the statusbar. */
1685 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001686
Chris Allegrettad26ab912003-01-28 01:16:47 +00001687 SET(DISABLE_CURPOS);
1688 statblank = 26;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001689}
1690
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001691/* If constant is false, the user typed ^C so we unconditionally display
Chris Allegrettad26ab912003-01-28 01:16:47 +00001692 * the cursor position. Otherwise, we display it only if the character
1693 * position changed, and DISABLE_CURPOS is not set.
1694 *
1695 * If constant and DISABLE_CURPOS is set, we unset it and update old_i and
1696 * old_totsize. That way, we leave the current statusbar alone, but next
1697 * time we will display. */
Chris Allegretta2084acc2001-11-29 03:43:08 +00001698int do_cursorpos(int constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001699{
Chris Allegrettad26ab912003-01-28 01:16:47 +00001700 const filestruct *fileptr;
1701 unsigned long i = 0;
1702 static unsigned long old_i = 0;
1703 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001704
Chris Allegrettad26ab912003-01-28 01:16:47 +00001705 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00001706
1707 if (old_totsize == -1)
1708 old_totsize = totsize;
1709
Chris Allegrettad26ab912003-01-28 01:16:47 +00001710 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
1711 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001712 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00001713 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001714 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00001715
Chris Allegrettad26ab912003-01-28 01:16:47 +00001716 if (constant && ISSET(DISABLE_CURPOS)) {
1717 UNSET(DISABLE_CURPOS);
1718 old_i = i;
1719 old_totsize = totsize;
1720 return 0;
1721 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00001722
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001723 /* If constant is false, display the position on the statusbar
1724 * unconditionally; otherwise, only display the position when the
1725 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00001726 if (!constant || old_i != i || old_totsize != totsize) {
1727 unsigned long xpt = xplustabs() + 1;
1728 unsigned long cur_len = strlenpt(current->data) + 1;
1729 int linepct = 100 * current->lineno / totlines;
1730 int colpct = 100 * xpt / cur_len;
1731 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
1732
1733 statusbar(
1734 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
1735 current->lineno, totlines, linepct,
1736 xpt, cur_len, colpct,
1737 i, totsize, bytepct);
1738 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00001739 }
1740
1741 old_i = i;
1742 old_totsize = totsize;
1743
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001744 reset_cursor();
Chris Allegrettad26ab912003-01-28 01:16:47 +00001745 return 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001746}
1747
Chris Allegretta2084acc2001-11-29 03:43:08 +00001748int do_cursorpos_void(void)
1749{
1750 return do_cursorpos(0);
1751}
1752
Chris Allegretta4640fe32003-02-10 03:10:03 +00001753/* Calculate the next line of help_text, starting at ptr. */
1754int line_len(const char *ptr)
1755{
1756 int j = 0;
1757
1758 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
1759 ptr++;
1760 j++;
1761 }
1762 if (j == COLS - 5) {
1763 /* Don't wrap at the first of two spaces following a period. */
1764 if (*ptr == ' ' && *(ptr + 1) == ' ')
1765 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001766 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00001767 while (*ptr != ' ' && j > 0) {
1768 ptr--;
1769 j--;
1770 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001771 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00001772 if (j == 0)
1773 j = COLS - 5;
1774 }
1775 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
1776 return j;
1777}
1778
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001779/* Our shortcut-list-compliant help function, which is better than
1780 * nothing, and dynamic! */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001781int do_help(void)
1782{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001783#ifndef DISABLE_HELP
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001784 int i, page = 0, kbinput = -1, meta, no_more = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001785 int no_help_flag = 0;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001786 const shortcut *oldshortcut;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001787
1788 blank_edit();
1789 curs_set(0);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001790 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001791 blank_statusbar();
1792
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001793 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00001794 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001795 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001796
1797 oldshortcut = currshortcut;
Chris Allegrettab3655b42001-10-22 03:15:31 +00001798
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001799 currshortcut = help_list;
Chris Allegretta6fe61492001-05-21 12:56:25 +00001800
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001801 if (ISSET(NO_HELP)) {
1802
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001803 /* Well, if we're going to do this, we should at least do it the
1804 * right way. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001805 no_help_flag = 1;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001806 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00001807 window_init();
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001808 bottombars(help_list);
Chris Allegretta70444892001-01-07 23:02:02 +00001809
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001810 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001811 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001812
1813 do {
Chris Allegrettaf717f982003-02-13 22:25:01 +00001814 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001815
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001816 switch (kbinput) {
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001817#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegretta598106e2002-01-19 01:59:37 +00001818 case KEY_MOUSE:
1819 do_mouse();
1820 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001821#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001822 case NANO_NEXTPAGE_KEY:
1823 case NANO_NEXTPAGE_FKEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001824 if (!no_more) {
1825 blank_edit();
1826 page++;
1827 }
1828 break;
1829 case NANO_PREVPAGE_KEY:
1830 case NANO_PREVPAGE_FKEY:
Chris Allegretta4640fe32003-02-10 03:10:03 +00001831 if (page > 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001832 no_more = 0;
1833 blank_edit();
1834 page--;
1835 }
1836 break;
1837 }
1838
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001839 /* Calculate where in the text we should be, based on the
1840 * page. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00001841 for (i = 1; i < page * (editwinrows - 1); i++) {
1842 ptr += line_len(ptr);
1843 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001844 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001845 }
1846
Chris Allegretta4640fe32003-02-10 03:10:03 +00001847 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
1848 int j = line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001849
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001850 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00001851 ptr += j;
1852 if (*ptr == '\n')
1853 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001854 }
Chris Allegretta4640fe32003-02-10 03:10:03 +00001855
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001856 if (*ptr == '\0') {
1857 no_more = 1;
1858 continue;
1859 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001860 } while ((kbinput = get_kbinput(edit, &meta, ISSET(REBIND_DELETE))) != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00001861
Chris Allegrettab3655b42001-10-22 03:15:31 +00001862 currshortcut = oldshortcut;
Chris Allegrettab3655b42001-10-22 03:15:31 +00001863
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001864 if (no_help_flag) {
Chris Allegretta70444892001-01-07 23:02:02 +00001865 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001866 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001867 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00001868 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00001869 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001870 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001871
1872 curs_set(1);
1873 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001874
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001875 /* The help_init() at the beginning allocated help_text, which has
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001876 * now been written to the screen. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001877 free(help_text);
1878 help_text = NULL;
1879
Chris Allegretta6df90f52002-07-19 01:08:59 +00001880#elif defined(DISABLE_HELP)
1881 nano_disabled_msg();
1882#endif
1883
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001884 return 1;
1885}
1886
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001887/* Highlight the current word being replaced or spell checked. We
1888 * expect word to have tabs and control characters expanded. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001889void do_replace_highlight(int highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00001890{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001891 int y = xplustabs();
1892 size_t word_len = strlen(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00001893
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001894 y = get_page_start(y) + COLS - y;
1895 /* Now y is the number of characters we can display on this
1896 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00001897
1898 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00001899
Chris Allegrettafb62f732000-12-05 11:36:41 +00001900 if (highlight_flag)
1901 wattron(edit, A_REVERSE);
1902
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001903 waddnstr(edit, word, y - 1);
1904
1905 if (word_len > y)
1906 waddch(edit, '$');
1907 else if (word_len == y)
1908 waddch(edit, word[word_len - 1]);
Chris Allegrettafb62f732000-12-05 11:36:41 +00001909
1910 if (highlight_flag)
1911 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00001912}
1913
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001914/* Fix editbot, based on the assumption that edittop is correct. */
1915void fix_editbot(void)
1916{
1917 int i;
1918
1919 editbot = edittop;
1920 for (i = 0; i < editwinrows && editbot->next != NULL; i++)
1921 editbot = editbot->next;
1922}
1923
1924#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001925/* Dump the passed-in file structure to stderr. */
1926void dump_buffer(const filestruct *inptr)
1927{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001928 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00001929 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001930 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00001931 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001932 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00001933 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001934
1935 while (inptr != NULL) {
1936 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
1937 inptr = inptr->next;
1938 }
1939}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001940
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001941/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00001942void dump_buffer_reverse(void)
1943{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001944 const filestruct *fileptr = filebot;
1945
1946 while (fileptr != NULL) {
1947 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
1948 fileptr = fileptr->prev;
1949 }
1950}
1951#endif /* DEBUG */
1952
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001953#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00001954#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001955#define XLCREDIT_LEN 8
1956
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001957void do_credits(void)
1958{
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001959 int i, j = 0, k, place = 0, start_x;
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001960
Chris Allegrettaf717f982003-02-13 22:25:01 +00001961 const char *what;
1962 const char *xlcredits[XLCREDIT_LEN];
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001963
Chris Allegrettaf717f982003-02-13 22:25:01 +00001964 const char *credits[CREDIT_LEN] = {
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001965 "0", /* "The nano text editor" */
1966 "1", /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001967 VERSION,
1968 "",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001969 "2", /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001970 "Chris Allegretta",
1971 "Jordi Mallach",
1972 "Adam Rogoyski",
1973 "Rob Siemborski",
1974 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001975 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00001976 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00001977 "Ken Tyler",
1978 "Sven Guckes",
1979 "Florian König",
1980 "Pauli Virtanen",
1981 "Daniele Medri",
1982 "Clement Laforet",
1983 "Tedi Heriyanto",
1984 "Bill Soudan",
1985 "Christian Weisgerber",
1986 "Erik Andersen",
1987 "Big Gaute",
1988 "Joshua Jensen",
1989 "Ryan Krebs",
1990 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00001991 "",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001992 "3", /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001993 "Plattsburgh State University",
1994 "Benet Laboratories",
1995 "Amy Allegretta",
1996 "Linda Young",
1997 "Jeremy Robichaud",
1998 "Richard Kolb II",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001999 "4", /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00002000 "Linus Torvalds",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00002001 "5", /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00002002 "Thomas Dickey",
2003 "Pavel Curtis",
2004 "Zeyd Ben-Halim",
2005 "Eric S. Raymond",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00002006 "6", /* "and anyone else we forgot..." */
2007 "7", /* "Thank you for using nano!\n" */
Chris Allegretta598106e2002-01-19 01:59:37 +00002008 "", "", "", "",
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00002009 "(c) 1999-2003 Chris Allegretta",
Chris Allegretta598106e2002-01-19 01:59:37 +00002010 "", "", "", "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00002011 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002012 };
2013
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00002014 xlcredits[0] = _("The nano text editor");
2015 xlcredits[1] = _("version ");
2016 xlcredits[2] = _("Brought to you by:");
2017 xlcredits[3] = _("Special thanks to:");
2018 xlcredits[4] = _("The Free Software Foundation");
2019 xlcredits[5] = _("For ncurses:");
2020 xlcredits[6] = _("and anyone else we forgot...");
2021 xlcredits[7] = _("Thank you for using nano!\n");
2022
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002023 curs_set(0);
2024 nodelay(edit, TRUE);
2025 blank_bottombars();
2026 mvwaddstr(topwin, 0, 0, hblank);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00002027 blank_edit();
2028 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002029 wrefresh(bottomwin);
2030 wrefresh(topwin);
2031
2032 while (wgetch(edit) == ERR) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00002033 for (k = 0; k <= 1; k++) {
2034 blank_edit();
Chris Allegretta598106e2002-01-19 01:59:37 +00002035 for (i = editwinrows / 2 - 1; i >= (editwinrows / 2 - 1 - j);
2036 i--) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00002037 mvwaddstr(edit, i * 2 - k, 0, hblank);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002038
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00002039 if (place - (editwinrows / 2 - 1 - i) < CREDIT_LEN) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00002040 what = credits[place - (editwinrows / 2 - 1 - i)];
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00002041
2042 /* God I've missed hacking. If what is exactly
2043 1 char long, it's a sentinel for a translated
2044 string, so use that instead. This means no
2045 thanking people with 1 character long names ;-) */
2046 if (strlen(what) == 1)
2047 what = xlcredits[atoi(what)];
2048 } else
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00002049 what = "";
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002050
Chris Allegretta17dcb722001-01-20 21:40:07 +00002051 start_x = COLS / 2 - strlen(what) / 2 - 1;
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00002052 mvwaddstr(edit, i * 2 - k, start_x, what);
2053 }
2054 usleep(700000);
2055 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002056 }
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002057 if (j < editwinrows / 2 - 1)
2058 j++;
2059
2060 place++;
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002061
2062 if (place >= CREDIT_LEN + editwinrows / 2)
2063 break;
2064 }
2065
2066 nodelay(edit, FALSE);
2067 curs_set(1);
2068 display_main_list();
2069 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00002070}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00002071#endif