blob: 87f0dfe8dfaac43083daf63177ce59f63d410c45 [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * winio.c *
4 * *
Jordi Mallach8ae57892002-01-04 17:57:40 +00005 * Copyright (C) 1999-2002 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
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000037int do_first_line(void)
38{
39 current = fileage;
40 placewewant = 0;
41 current_x = 0;
Chris Allegretta234a34d2000-07-29 04:33:38 +000042 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000043 return 1;
44}
45
46int do_last_line(void)
47{
48 current = filebot;
49 placewewant = 0;
50 current_x = 0;
Chris Allegretta234a34d2000-07-29 04:33:38 +000051 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000052 return 1;
53}
54
Chris Allegretta6df90f52002-07-19 01:08:59 +000055/* Return the placewewant associated with current_x. That is, xplustabs
56 * is the zero-based column position of the cursor. Value is no smaller
57 * than current_x. */
58size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000059{
Chris Allegretta6df90f52002-07-19 01:08:59 +000060 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000061}
62
Chris Allegretta6df90f52002-07-19 01:08:59 +000063/* Return what current_x should be, given xplustabs() for the line. */
64size_t actual_x(const filestruct *fileptr, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000065{
Chris Allegretta6df90f52002-07-19 01:08:59 +000066 size_t i = 0;
67 /* the position in fileptr->data, returned */
68 size_t length = 0;
69 /* the screen display width to data[i] */
70 char *c;
71 /* fileptr->data + i */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000072
Chris Allegretta6df90f52002-07-19 01:08:59 +000073 assert(fileptr != NULL && fileptr->data != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000074
Chris Allegretta6df90f52002-07-19 01:08:59 +000075 for (c = fileptr->data; length < xplus && *c != '\0'; i++, c++) {
76 if (*c == '\t')
77 length += tabsize - length % tabsize;
Chris Allegrettacf287c82002-07-20 13:57:41 +000078 else if (is_cntrl_char((int)*c))
Chris Allegretta6df90f52002-07-19 01:08:59 +000079 length += 2;
Chris Allegretta6df90f52002-07-19 01:08:59 +000080 else
81 length++;
82 }
83 assert(length == strnlenpt(fileptr->data, i));
84 assert(i <= strlen(fileptr->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000085
Chris Allegretta6df90f52002-07-19 01:08:59 +000086 if (length > xplus)
87 i--;
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000088
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000089#ifdef DEBUG
Chris Allegretta6df90f52002-07-19 01:08:59 +000090 fprintf(stderr, _("actual_x for xplus=%d returns %d\n"), xplus, i);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000091#endif
Chris Allegretta4dc03d52002-05-11 03:04:44 +000092
Chris Allegretta6df90f52002-07-19 01:08:59 +000093 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +000094}
95
Chris Allegretta6df90f52002-07-19 01:08:59 +000096/* A strlen with tabs factored in, similar to xplustabs(). */
97size_t strnlenpt(const char *buf, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +000098{
Chris Allegretta6df90f52002-07-19 01:08:59 +000099 size_t length = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000100
Chris Allegretta6df90f52002-07-19 01:08:59 +0000101 if (buf != NULL)
102 for (; *buf != '\0' && size != 0; size--, buf++) {
103 if (*buf == '\t')
104 length += tabsize - (length % tabsize);
Chris Allegrettacf287c82002-07-20 13:57:41 +0000105 else if (is_cntrl_char((int)*buf))
Chris Allegretta6df90f52002-07-19 01:08:59 +0000106 length += 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000107 else
Chris Allegretta6df90f52002-07-19 01:08:59 +0000108 length++;
109 }
110 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000111}
112
Chris Allegretta6df90f52002-07-19 01:08:59 +0000113size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +0000114{
Chris Allegretta6df90f52002-07-19 01:08:59 +0000115 return strnlenpt(buf, -1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +0000116}
117
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000118void blank_bottombars(void)
119{
Chris Allegretta6df90f52002-07-19 01:08:59 +0000120 if (!no_help()) {
121 mvwaddstr(bottomwin, 1, 0, hblank);
122 mvwaddstr(bottomwin, 2, 0, hblank);
123 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000124}
125
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000126void blank_bottomwin(void)
127{
128 if (ISSET(NO_HELP))
129 return;
130
131 mvwaddstr(bottomwin, 1, 0, hblank);
132 mvwaddstr(bottomwin, 2, 0, hblank);
133}
134
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000135void blank_edit(void)
136{
137 int i;
138 for (i = 0; i <= editwinrows - 1; i++)
139 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000140}
141
142
143void blank_statusbar(void)
144{
145 mvwaddstr(bottomwin, 0, 0, hblank);
146}
147
148void blank_statusbar_refresh(void)
149{
150 blank_statusbar();
151 wrefresh(bottomwin);
152}
153
154void check_statblank(void)
155{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000156 if (statblank > 1)
157 statblank--;
158 else if (statblank == 1 && !ISSET(CONSTUPDATE)) {
159 statblank--;
160 blank_statusbar_refresh();
161 }
162}
163
Chris Allegretta6df90f52002-07-19 01:08:59 +0000164/* Repaint the statusbar when getting a character in nanogetstr. buf
165 * should be no longer than COLS - 4.
166 *
167 * Note that we must turn on A_REVERSE here, since do_help turns it
168 * off! */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000169void nanoget_repaint(const char *buf, const char *inputbuf, int x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000170{
Chris Allegretta6df90f52002-07-19 01:08:59 +0000171 int len = strlen(buf) + 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +0000172 int wid = COLS - len;
173
Chris Allegretta6df90f52002-07-19 01:08:59 +0000174 assert(wid >= 2);
175 assert(0 <= x && x <= strlen(inputbuf));
176
Chris Allegrettab3655b42001-10-22 03:15:31 +0000177 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000178 blank_statusbar();
Chris Allegretta6df90f52002-07-19 01:08:59 +0000179 mvwaddstr(bottomwin, 0, 0, buf);
180 waddch(bottomwin, ':');
181 waddch(bottomwin, x < wid ? ' ' : '$');
182 waddnstr(bottomwin, &inputbuf[wid * (x / wid)], wid);
183 wmove(bottomwin, 0, (x % wid) + len);
Chris Allegrettab3655b42001-10-22 03:15:31 +0000184 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +0000185}
186
Chris Allegretta6df90f52002-07-19 01:08:59 +0000187/* Get the input from the kb; this should only be called from
188 * statusq(). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000189int nanogetstr(int allowtabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +0000190#ifndef NANO_SMALL
191 historyheadtype *history_list,
192#endif
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000193 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +0000194#ifndef DISABLE_TABCOMP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000195 , int *list
Chris Allegrettabe77c612000-11-24 14:00:16 +0000196#endif
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000197 )
Chris Allegretta6df90f52002-07-19 01:08:59 +0000198{
199 int kbinput;
200 int x;
201 /* the cursor position in 'answer' */
202 int xend;
203 /* length of 'answer', the status bar text */
204 int tabbed = 0;
205 /* used by input_tab() */
206 const shortcut *t;
Chris Allegretta598106e2002-01-19 01:59:37 +0000207
Chris Allegretta5beed502003-01-05 20:41:21 +0000208#ifndef NANO_SMALL
209 /* for history */
210 char *history = NULL;
211 char *complete = NULL;
212 int last_kbinput = 0;
213#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +0000214 xend = strlen(def);
215 x = xend;
216 answer = (char *)nrealloc(answer, xend + 1);
217 if (xend > 0)
218 strcpy(answer, def);
219 else
220 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000221
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000222#if !defined(DISABLE_HELP) || (!defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION))
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000223 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +0000224#endif
225
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000226 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +0000227
Chris Allegretta6df90f52002-07-19 01:08:59 +0000228 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000229
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000230 /* Make sure any editor screen updates are displayed before getting
231 input */
Chris Allegretta022b96f2000-11-14 17:47:58 +0000232 wrefresh(edit);
233
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000234 while ((kbinput = wgetch(bottomwin)) != 13) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000235 for (t = s; t != NULL; t = t->next) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000236#ifdef DEBUG
237 fprintf(stderr, _("Aha! \'%c\' (%d)\n"), kbinput, kbinput);
238#endif
239
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000240 if (kbinput == t->val && kbinput < 32) {
Chris Allegretta5bf51d32000-11-16 06:01:10 +0000241
Chris Allegrettab3655b42001-10-22 03:15:31 +0000242#ifndef DISABLE_HELP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000243 /* Have to do this here, it would be too late to do it
244 in statusq() */
Chris Allegretta598106e2002-01-19 01:59:37 +0000245 if (kbinput == NANO_HELP_KEY || kbinput == NANO_HELP_FKEY) {
Chris Allegrettab3655b42001-10-22 03:15:31 +0000246 do_help();
247 break;
248 }
249#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000250 return t->val;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000251 }
252 }
Chris Allegretta6df90f52002-07-19 01:08:59 +0000253 assert(0 <= x && x <= xend && xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000254
Chris Allegretta04d848e2000-11-05 17:54:41 +0000255 if (kbinput != '\t')
256 tabbed = 0;
257
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000258 switch (kbinput) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000259
Chris Allegretta598106e2002-01-19 01:59:37 +0000260 /* Stuff we want to equate with <enter>, ASCII 13 */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000261 case 343:
Chris Allegrettaf9b6c9b2000-10-18 19:35:59 +0000262 ungetch(13); /* Enter on iris-ansi $TERM, sometimes */
263 break;
Chris Allegretta598106e2002-01-19 01:59:37 +0000264 /* Stuff we want to ignore */
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000265#ifdef PDCURSES
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000266 case 541:
267 case 542:
Chris Allegretta598106e2002-01-19 01:59:37 +0000268 case 543: /* Right ctrl again */
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000269 case 544:
Chris Allegretta598106e2002-01-19 01:59:37 +0000270 case 545: /* Right alt again */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000271 break;
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000272#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000273#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000274 case KEY_MOUSE:
275 do_mouse();
276 break;
277#endif
Chris Allegretta658399a2001-06-14 02:54:22 +0000278 case NANO_HOME_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000279 case KEY_HOME:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000280 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000281 break;
Chris Allegretta658399a2001-06-14 02:54:22 +0000282 case NANO_END_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000283 case KEY_END:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000284 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000285 break;
286 case KEY_RIGHT:
Chris Allegretta35dac582001-03-21 15:07:20 +0000287 case NANO_FORWARD_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000288 if (x < xend)
289 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000290 break;
291 case NANO_CONTROL_D:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000292 if (x < xend) {
293 memmove(answer + x, answer + x + 1, xend - x);
294 xend--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000295 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000296 break;
297 case NANO_CONTROL_K:
298 case NANO_CONTROL_U:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000299 null_at(&answer, 0);
300 xend = 0;
301 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000302 break;
303 case KEY_BACKSPACE:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000304 case 127:
305 case NANO_CONTROL_H:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000306 if (x > 0) {
307 memmove(answer + x - 1, answer + x, xend - x + 1);
Chris Allegretta04d848e2000-11-05 17:54:41 +0000308 x--;
Chris Allegretta6df90f52002-07-19 01:08:59 +0000309 xend--;
310 }
Chris Allegretta04d848e2000-11-05 17:54:41 +0000311 break;
312 case NANO_CONTROL_I:
Chris Allegretta5beed502003-01-05 20:41:21 +0000313#ifndef NANO_SMALL
314 /* tab history completion */
315 if (history_list) {
316 if ((!complete) || (last_kbinput != NANO_CONTROL_I)) {
317 history_list->current = (historytype *)history_list;
318 history_list->len = strlen(answer);
319 }
Chris Allegretta6df90f52002-07-19 01:08:59 +0000320
Chris Allegretta5beed502003-01-05 20:41:21 +0000321 if (history_list->len) {
322 complete = get_history_completion(history_list, answer);
323 xend = strlen(complete);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000324 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +0000325 answer = mallocstrcpy(answer, complete);
326 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000327 }
Chris Allegretta5beed502003-01-05 20:41:21 +0000328#ifndef DISABLE_TABCOMP
329 else {
Chris Allegrettabe77c612000-11-24 14:00:16 +0000330#endif
Chris Allegretta5beed502003-01-05 20:41:21 +0000331#endif
332#ifndef DISABLE_TABCOMP
333 if (allowtabs) {
334 int shift = 0;
335
336 answer = input_tab(answer, x, &tabbed, &shift, list);
337 xend = strlen(answer);
338 x += shift;
339 if (x > xend)
340 x = xend;
341 }
342 }
343#endif
344 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000345 case KEY_LEFT:
Chris Allegretta35dac582001-03-21 15:07:20 +0000346 case NANO_BACK_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000347 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000348 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000349 break;
350 case KEY_UP:
Chris Allegretta5beed502003-01-05 20:41:21 +0000351#ifndef NANO_SMALL
352 if (history_list) {
353 /* get older search from the history list */
354 if ((history = get_history_older(history_list))) {
355 answer = mallocstrcpy(answer, history);
356 xend = strlen(history);
357 } else {
358 answer = mallocstrcpy(answer, "");
359 xend = 0;
360 }
361 x = xend;
362 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000363 break;
Chris Allegretta5beed502003-01-05 20:41:21 +0000364#endif
365 case KEY_DOWN:
366#ifndef NANO_SMALL
367 if (history_list) {
368 /* get newer search from the history list */
369 if ((history = get_history_newer(history_list))) {
370 answer = mallocstrcpy(answer, history);
371 xend = strlen(history);
372 } else {
373 answer = mallocstrcpy(answer, "");
374 xend = 0;
375 }
376 x = xend;
377 }
378#endif
379 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000380 case KEY_DC:
381 goto do_deletekey;
382
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000383 case 27:
384 switch (kbinput = wgetch(edit)) {
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000385 case 'O':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000386 switch (kbinput = wgetch(edit)) {
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000387 case 'F':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000388 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000389 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000390 case 'H':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000391 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000392 break;
393 }
394 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000395 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000396 switch (kbinput = wgetch(edit)) {
397 case 'C':
398 if (x < xend)
399 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000400 break;
401 case 'D':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000402 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000403 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000404 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000405 case '1':
406 case '7':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000407 x = 0;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000408 goto skip_tilde;
409 case '3':
410 do_deletekey:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000411 if (x < xend) {
412 memmove(answer + x, answer + x + 1, xend - x);
413 xend--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000414 }
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000415 goto skip_tilde;
416 case '4':
417 case '8':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000418 x = xend;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000419 goto skip_tilde;
420 skip_tilde:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000421 nodelay(edit, TRUE);
422 kbinput = wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000423 if (kbinput == '~' || kbinput == ERR)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000424 kbinput = -1;
425 nodelay(edit, FALSE);
426 break;
427 }
Chris Allegretta6df90f52002-07-19 01:08:59 +0000428 break;
Chris Allegretta658399a2001-06-14 02:54:22 +0000429 default:
430
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000431 for (t = s; t != NULL; t = t->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +0000432#ifdef DEBUG
Chris Allegretta598106e2002-01-19 01:59:37 +0000433 fprintf(stderr, _("Aha! \'%c\' (%d)\n"), kbinput,
434 kbinput);
Chris Allegretta658399a2001-06-14 02:54:22 +0000435#endif
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000436 if (kbinput == t->val || kbinput == t->val - 32) {
Chris Allegretta658399a2001-06-14 02:54:22 +0000437 /* We hit an Alt key. Do like above. We don't
438 just ungetch the letter and let it get caught
439 above cause that screws the keypad... */
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000440 return t->val;
Chris Allegretta658399a2001-06-14 02:54:22 +0000441 }
442 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000443 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000444 break;
445
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000446 default:
447 if (kbinput < 32)
448 break;
Chris Allegretta6df90f52002-07-19 01:08:59 +0000449 answer = nrealloc(answer, xend + 2);
450 memmove(answer + x + 1, answer + x, xend - x + 1);
451 xend++;
452 answer[x] = kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000453 x++;
454
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000455#ifdef DEBUG
456 fprintf(stderr, _("input \'%c\' (%d)\n"), kbinput, kbinput);
457#endif
Chris Allegretta5beed502003-01-05 20:41:21 +0000458 } /* switch (kbinput) */
Chris Allegrettaa65ba512003-01-05 20:57:07 +0000459#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +0000460 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +0000461#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +0000462 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000463 wrefresh(bottomwin);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000464 } /* while (kbinput ...) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000465
Chris Allegretta6df90f52002-07-19 01:08:59 +0000466 /* In Pico mode, just check for a blank answer here */
Chris Allegretta4dc03d52002-05-11 03:04:44 +0000467 if (ISSET(PICO_MODE) && answer[0] == '\0')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000468 return -2;
469 else
470 return 0;
471}
472
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000473/* If modified is not already set, set it and update titlebar. */
474void set_modified(void)
475{
476 if (!ISSET(MODIFIED)) {
477 SET(MODIFIED);
478 titlebar(NULL);
479 wrefresh(topwin);
480 }
481}
482
Chris Allegretta6df90f52002-07-19 01:08:59 +0000483void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000484{
485 int namelen, space;
Chris Allegretta6df90f52002-07-19 01:08:59 +0000486 const char *what = path;
Chris Allegrettaf4b96012001-01-03 07:11:47 +0000487
488 if (path == NULL)
489 what = filename;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000490
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000491 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +0000492
Chris Allegretta6df90f52002-07-19 01:08:59 +0000493 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyc5967552002-06-21 03:20:06 +0000494 mvwaddnstr(topwin, 0, 2, VERMSG, COLS - 3);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000495
Chris Allegretta6df90f52002-07-19 01:08:59 +0000496 space = COLS - sizeof(VERMSG) - 22;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000497
Chris Allegrettaf4b96012001-01-03 07:11:47 +0000498 namelen = strlen(what);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000499
David Lawrence Ramseyc5967552002-06-21 03:20:06 +0000500 if (space > 0) {
501 if (what[0] == '\0')
Chris Allegretta6df90f52002-07-19 01:08:59 +0000502 mvwaddnstr(topwin, 0, COLS / 2 - 6, _("New Buffer"),
503 COLS / 2 + COLS % 2 - 6);
504 else if (namelen > space) {
505 if (path == NULL)
506 waddstr(topwin, _(" File: ..."));
507 else
508 waddstr(topwin, _(" DIR: ..."));
509 waddstr(topwin, &what[namelen - space]);
510 } else {
511 if (path == NULL)
512 mvwaddstr(topwin, 0, COLS / 2 - (namelen / 2 + 1),
513 _("File: "));
514 else
515 mvwaddstr(topwin, 0, COLS / 2 - (namelen / 2 + 1),
516 _(" DIR: "));
517 waddstr(topwin, what);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000518 }
David Lawrence Ramseyc5967552002-06-21 03:20:06 +0000519 } /* If we don't have space, we shouldn't bother */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000520 if (ISSET(MODIFIED))
Chris Allegretta6df90f52002-07-19 01:08:59 +0000521 mvwaddnstr(topwin, 0, COLS - 11, _(" Modified "), 11);
Chris Allegretta4dc03d52002-05-11 03:04:44 +0000522 else if (ISSET(VIEW_MODE))
Chris Allegretta6df90f52002-07-19 01:08:59 +0000523 mvwaddnstr(topwin, 0, COLS - 11, _(" View "), 11);
Chris Allegretta8ce24132001-04-30 11:28:46 +0000524
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000525 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +0000526
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000527 wrefresh(topwin);
528 reset_cursor();
529}
530
Chris Allegretta6232d662002-05-12 19:52:15 +0000531void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000532{
Chris Allegrettabc72e362002-02-16 20:03:44 +0000533 int i, j, numcols;
Chris Allegretta6232d662002-05-12 19:52:15 +0000534 char keystr[4];
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000535 int slen;
536
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000537 if (ISSET(NO_HELP))
538 return;
539
Chris Allegretta6232d662002-05-12 19:52:15 +0000540 if (s == main_list) {
541 slen = MAIN_VISIBLE;
542 assert(MAIN_VISIBLE <= length_of_list(s));
543 } else
544 slen = length_of_list(s);
545
Chris Allegretta6232d662002-05-12 19:52:15 +0000546 /* There will be this many columns of shortcuts */
547 numcols = (slen + (slen % 2)) / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000548
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000549 blank_bottomwin();
Chris Allegretta658399a2001-06-14 02:54:22 +0000550
Chris Allegrettabc72e362002-02-16 20:03:44 +0000551 for (i = 0; i < numcols; i++) {
552 for (j = 0; j <= 1; j++) {
Chris Allegretta658399a2001-06-14 02:54:22 +0000553
Chris Allegretta6232d662002-05-12 19:52:15 +0000554 wmove(bottomwin, 1 + j, i * (COLS / numcols));
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000555
Chris Allegretta5beed502003-01-05 20:41:21 +0000556 /* Yucky sentinel values we can't handle a better way */
Chris Allegretta6232d662002-05-12 19:52:15 +0000557 if (s->val == NANO_CONTROL_SPACE)
558 strcpy(keystr, "^ ");
Chris Allegrettaa65ba512003-01-05 20:57:07 +0000559#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +0000560 else if (s->val == KEY_UP)
561 strcpy(keystr, _("Up"));
562#endif /* NANO_SMALL */
563 else if (s->val > 0) {
Chris Allegretta6232d662002-05-12 19:52:15 +0000564 if (s->val < 64)
565 sprintf(keystr, "^%c", s->val + 64);
566 else
567 sprintf(keystr, "M-%c", s->val - 32);
568 } else if (s->altval > 0)
569 sprintf(keystr, "M-%c", s->altval);
Chris Allegretta658399a2001-06-14 02:54:22 +0000570
Chris Allegretta6232d662002-05-12 19:52:15 +0000571 onekey(keystr, s->desc, COLS / numcols);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000572
Chris Allegretta6232d662002-05-12 19:52:15 +0000573 s = s->next;
574 if (s == NULL)
575 goto break_completely_out;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000576 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000577 }
578
Chris Allegretta6df90f52002-07-19 01:08:59 +0000579 break_completely_out:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000580 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000581}
582
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000583/* Write a shortcut key to the help area at the bottom of the window.
584 * keystroke is e.g. "^G" and desc is e.g. "Get Help".
585 * We are careful to write exactly len characters, even if len is
586 * very small and keystroke and desc are long. */
587void onekey(const char *keystroke, const char *desc, int len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000588{
Chris Allegretta5beed502003-01-05 20:41:21 +0000589
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000590 wattron(bottomwin, A_REVERSE);
591 waddnstr(bottomwin, keystroke, len);
592 wattroff(bottomwin, A_REVERSE);
593 len -= strlen(keystroke);
594 if (len > 0) {
595 waddch(bottomwin, ' ');
596 len--;
597 waddnstr(bottomwin, desc, len);
598 len -= strlen(desc);
599 for (; len > 0; len--)
600 waddch(bottomwin, ' ');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000601 }
602}
603
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000604/* And so start the display update routines. */
605
606#ifndef NDEBUG
607int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000608{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000609 int check_line = 0;
610 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000611
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000612 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
613 check_line++;
614 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000615}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000616#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +0000617
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000618 /* nano scrolls horizontally within a line in chunks. This function
619 * returns the column number of the first character displayed in the
620 * window when the cursor is at the given column. */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000621int get_page_start(int column)
Chris Allegretta6df90f52002-07-19 01:08:59 +0000622{
623 assert(COLS > 9);
624 return column < COLS - 1 ? 0 : column - 7 - (column - 8) % (COLS - 9);
625}
626
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000627/* Resets current_y, based on the position of current, and puts the
628 * cursor at (current_y, current_x). */
629void reset_cursor(void)
630{
631 const filestruct *ptr = edittop;
632 size_t x;
633
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000634 /* Yuck. This condition can be true after open_file() when opening
635 * the first file. */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000636 if (edittop == NULL)
637 return;
638
639 current_y = 0;
640
641 while (ptr != current && ptr != editbot && ptr->next != NULL) {
642 ptr = ptr->next;
643 current_y++;
644 }
645
646 x = xplustabs();
647 wmove(edit, current_y, x - get_page_start(x));
648}
Chris Allegretta6df90f52002-07-19 01:08:59 +0000649
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000650/* edit_add() takes care of the job of actually painting a line into
651 * the edit window. Called only from update_line(). Expects a
652 * converted-to-not-have-tabs line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000653void edit_add(const filestruct *fileptr, int yval, int start
654#ifndef NANO_SMALL
655 , int virt_mark_beginx, int virt_cur_x
656#endif
657 )
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000658{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000659#ifdef DEBUG
660 fprintf(stderr, "Painting line %d, current is %d\n", fileptr->lineno,
661 current->lineno);
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000662#endif
663
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000664 /* Just paint the string in any case (we'll add color or reverse on
Chris Allegretta598106e2002-01-19 01:59:37 +0000665 just the text that needs it */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000666 mvwaddnstr(edit, yval, 0, &fileptr->data[start], COLS);
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000667
Chris Allegretta7dd77682001-12-08 19:52:28 +0000668#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +0000669 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000670 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000671
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000672 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
673 int x_start;
674 /* Starting column for mvwaddnstr. Zero-based. */
675 int paintlen;
676 /* number of chars to paint on this line. There are COLS
677 * characters on a whole line. */
678 regex_t start_regexp; /* Compiled search regexp */
679 regmatch_t startmatch; /* match position for start_regexp*/
680 regmatch_t endmatch; /* match position for end_regexp*/
681
682 regcomp(&start_regexp, tmpcolor->start, REG_EXTENDED);
683
684 if (tmpcolor->bright)
685 wattron(edit, A_BOLD);
686 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
687 /* Two notes about regexec. Return value 0 means there is a
688 * match. Also, rm_eo is the first non-matching character
689 * after the match. */
690
691 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000692 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000693 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000694
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000695 /* We increment k by rm_eo, to move past the end of the
696 last match. Even though two matches may overlap, we
697 want to ignore them, so that we can highlight C-strings
698 correctly. */
699 while (k < start + COLS) {
700 /* Note the fifth parameter to regexec. It says not to
701 * match the beginning-of-line character unless
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000702 * k == 0. If regexec returns nonzero, there are no
703 * more matches in the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000704 if (regexec(&start_regexp, &fileptr->data[k], 1,
705 &startmatch, k == 0 ? 0 : REG_NOTBOL))
706 break;
707 /* Translate the match to the beginning of the line. */
708 startmatch.rm_so += k;
709 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +0000710 if (startmatch.rm_so == startmatch.rm_eo) {
711 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +0000712 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +0000713 } else if (startmatch.rm_so < start + COLS &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000714 startmatch.rm_eo > start) {
715 x_start = startmatch.rm_so - start;
716 if (x_start < 0)
717 x_start = 0;
718 paintlen = startmatch.rm_eo - start - x_start;
719 if (paintlen > COLS - x_start)
720 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000721
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000722 assert(0 <= x_start && 0 < paintlen &&
723 x_start + paintlen <= COLS);
724 mvwaddnstr(edit, yval, x_start,
725 fileptr->data + start + x_start, paintlen);
726 }
727 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +0000728 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000729 } else {
730 /* This is a multi-line regexp. There are two steps.
731 * First, we have to see if the beginning of the line is
732 * colored by a start on an earlier line, and an end on
733 * this line or later.
734 *
735 * We find the first line before fileptr matching the
736 * start. If every match on that line is followed by an
737 * end, then go to step two. Otherwise, find the next line
738 * after start_line matching the end. If that line is not
739 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +0000740
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000741 regex_t end_regexp; /* Compiled search regexp */
742 const filestruct *start_line = fileptr->prev;
743 /* the first line before fileptr matching start*/
744 regoff_t start_col;
745 /* where it starts in that line */
746 const filestruct *end_line;
747 int searched_later_lines = 0;
748 /* Used in step 2. Have we looked for an end on
749 * lines after fileptr? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000750
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000751 regcomp(&end_regexp, tmpcolor->end, REG_EXTENDED);
752
753 while (start_line != NULL &&
754 regexec(&start_regexp, start_line->data, 1,
755 &startmatch, 0)) {
756 /* If there is an end on this line, there is no need
757 * to look for starts on earlier lines. */
758 if (!regexec(&end_regexp, start_line->data, 1,
759 &endmatch, 0))
760 goto step_two;
761 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000762 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000763 /* No start found, so skip to the next step. */
764 if (start_line == NULL)
765 goto step_two;
766 /* Now start_line is the first line before fileptr
767 * containing a start match. Is there a start on this
768 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000769
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000770 start_col = 0;
771 while (1) {
772 start_col += startmatch.rm_so;
773 startmatch.rm_eo -= startmatch.rm_so;
774 if (regexec(&end_regexp,
775 start_line->data + start_col + startmatch.rm_eo,
776 1, &endmatch,
777 start_col + startmatch.rm_eo == 0 ? 0 : REG_NOTBOL))
778 /* No end found after this start */
779 break;
780 start_col++;
781 if (regexec(&start_regexp,
782 start_line->data + start_col, 1, &startmatch,
783 REG_NOTBOL))
784 /* No later start on this line. */
785 goto step_two;
786 }
787 /* Indeed, there is a start not followed on this line by an
788 * end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000789
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000790 /* We have already checked that there is no end before
791 * fileptr and after the start. Is there an end after
792 * the start at all? We don't paint unterminated starts. */
793 end_line = fileptr;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000794 while (end_line != NULL && regexec(&end_regexp, end_line->data,
795 1, &endmatch, 0))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000796 end_line = end_line->next;
797
798 /* No end found, or it is too early. */
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000799 if (end_line == NULL || end_line->lineno < fileptr->lineno ||
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000800 (end_line == fileptr && endmatch.rm_eo <= start))
801 goto step_two;
802
803 /* Now paint the start of fileptr. */
804 paintlen = end_line != fileptr
805 ? COLS : endmatch.rm_eo - start;
806 if (paintlen > COLS)
807 paintlen = COLS;
808
809 assert(0 < paintlen && paintlen <= COLS);
810 mvwaddnstr(edit, yval, 0, fileptr->data + start, paintlen);
811
812 /* We have already painted the whole line. */
813 if (paintlen == COLS)
814 goto skip_step_two;
815
816
817 step_two: /* Second step, we look for starts on this line. */
818 start_col = 0;
819 while (start_col < start + COLS) {
820 if (regexec(&start_regexp, fileptr->data + start_col, 1,
821 &startmatch, start_col == 0 ? 0 : REG_NOTBOL)
822 || start_col + startmatch.rm_so >= start + COLS)
823 /* No more starts on this line. */
824 break;
825 /* Translate the match to be relative to the
826 * beginning of the line. */
827 startmatch.rm_so += start_col;
828 startmatch.rm_eo += start_col;
829
830 x_start = startmatch.rm_so - start;
831 if (x_start < 0) {
832 x_start = 0;
833 startmatch.rm_so = start;
834 }
835 if (!regexec(&end_regexp, fileptr->data + startmatch.rm_eo,
836 1, &endmatch,
837 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL)) {
838 /* Translate the end match to be relative to the
839 beginning of the line. */
840 endmatch.rm_so += startmatch.rm_eo;
841 endmatch.rm_eo += startmatch.rm_eo;
842 /* There is an end on this line. But does it
843 appear on this page, and is the match more than
844 zero characters long? */
845 if (endmatch.rm_eo > start &&
846 endmatch.rm_eo > startmatch.rm_so) {
847 paintlen = endmatch.rm_eo - start - x_start;
848 if (x_start + paintlen > COLS)
849 paintlen = COLS - x_start;
850
851 assert(0 <= x_start && 0 < paintlen &&
852 x_start + paintlen <= COLS);
853 mvwaddnstr(edit, yval, x_start,
854 fileptr->data + start + x_start, paintlen);
855 }
856 } else if (!searched_later_lines) {
857 searched_later_lines = 1;
858 /* There is no end on this line. But we haven't
859 * yet looked for one on later lines. */
860 end_line = fileptr->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000861 while (end_line != NULL && regexec(&end_regexp,
862 end_line->data, 1, &endmatch, 0))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000863 end_line = end_line->next;
864 if (end_line != NULL) {
865 assert(0 <= x_start && x_start < COLS);
866 mvwaddnstr(edit, yval, x_start,
867 fileptr->data + start + x_start,
868 COLS - x_start);
869 /* We painted to the end of the line, so
870 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000871 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +0000872 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000873 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000874 start_col = startmatch.rm_so + 1;
875 } /* while start_col < start + COLS */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000876
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000877 skip_step_two:
878 regfree(&end_regexp);
879 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000880
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000881 regfree(&start_regexp);
882 wattroff(edit, A_BOLD);
883 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
884 } /* for tmpcolor in colorstrings */
885 }
Chris Allegretta598106e2002-01-19 01:59:37 +0000886#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000887
Chris Allegretta7dd77682001-12-08 19:52:28 +0000888#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000889 if (ISSET(MARK_ISSET)
890 && (fileptr->lineno <= mark_beginbuf->lineno
891 || fileptr->lineno <= current->lineno)
892 && (fileptr->lineno >= mark_beginbuf->lineno
893 || fileptr->lineno >= current->lineno)) {
894 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000895
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000896 int x_start;
897 /* Starting column for mvwaddnstr. Zero-based. */
898 int paintlen;
899 /* number of chars to paint on this line. There are COLS
900 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +0000901
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000902 if (mark_beginbuf == fileptr && current == fileptr) {
903 x_start = virt_mark_beginx < virt_cur_x ? virt_mark_beginx
904 : virt_cur_x;
905 paintlen = abs(virt_mark_beginx - virt_cur_x);
906 } else {
907 if (mark_beginbuf->lineno < fileptr->lineno ||
908 current->lineno < fileptr->lineno)
909 x_start = 0;
910 else
911 x_start = mark_beginbuf == fileptr ? virt_mark_beginx
912 : virt_cur_x;
913
914 if (mark_beginbuf->lineno > fileptr->lineno ||
915 current->lineno > fileptr->lineno)
916 paintlen = start + COLS;
917 else
918 paintlen = mark_beginbuf == fileptr ? virt_mark_beginx
919 : virt_cur_x;
920 }
921 x_start -= start;
922 if (x_start < 0) {
923 paintlen += x_start;
924 x_start = 0;
925 }
926 if (x_start + paintlen > COLS)
927 paintlen = COLS - x_start;
928 if (paintlen > 0) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000929 wattron(edit, A_REVERSE);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000930 assert(x_start >= 0 && paintlen > 0 && x_start + paintlen <= COLS);
931 mvwaddnstr(edit, yval, x_start,
932 fileptr->data + start + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000933 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000934 }
Chris Allegretta08893e02001-11-29 02:42:27 +0000935 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000936#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000937}
938
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000939/* Just update one line in the edit buffer. Basically a wrapper for
940 * edit_add(). If fileptr != current, then index is considered 0.
941 * The line will be displayed starting with fileptr->data[index].
942 * Likely args are current_x or 0. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000943void update_line(filestruct *fileptr, int index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000944{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000945 int line;
946 /* line in the edit window for CURSES calls */
947#ifndef NANO_SMALL
948 int virt_cur_x;
949 int virt_mark_beginx;
950#endif
951 char *original;
952 /* The original string fileptr->data. */
953 char *converted;
954 /* fileptr->data converted to have tabs and control characters
955 * expanded. */
956 size_t pos;
957 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000958
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000959 if (fileptr == NULL)
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000960 return;
Robert Siemborski53154a72000-06-18 00:11:03 +0000961
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000962 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000963
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000964 /* We assume the line numbers are valid. Is that really true? */
965 assert(line < 0 || line == check_linenumbers(fileptr));
966
967 if (line < 0 || line >= editwinrows)
968 return;
969
970 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000971 mvwaddstr(edit, line, 0, hblank);
972
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000973 original = fileptr->data;
974 converted = charalloc(strlenpt(original) + 1);
Chris Allegretta5beed502003-01-05 20:41:21 +0000975
976 /* Next, convert all the tabs to spaces, so everything else is easy.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000977 * Note the internal speller sends us index == -1. */
978 index = fileptr == current && index > 0 ? strnlenpt(original, index) : 0;
979#ifndef NANO_SMALL
980 virt_cur_x = fileptr == current ? strnlenpt(original, current_x) : current_x;
981 virt_mark_beginx = fileptr == mark_beginbuf ? strnlenpt(original, mark_beginx) : mark_beginx;
982#endif
Robert Siemborski53875912000-06-16 04:25:30 +0000983
984 pos = 0;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000985 for (; *original != '\0'; original++) {
986 if (*original == '\t')
Robert Siemborski53875912000-06-16 04:25:30 +0000987 do {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000988 converted[pos++] = ' ';
Chris Allegretta6d690a32000-08-03 22:51:21 +0000989 } while (pos % tabsize);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000990 else if (is_cntrl_char(*original)) {
991 converted[pos++] = '^';
992 if (*original == 127)
993 converted[pos++] = '?';
994 else if (*original == '\n')
995 /* Treat newlines (ASCII 10's) embedded in a line as encoded
996 * nulls (ASCII 0's); the line in question should be run
997 * through unsunder() before reaching here */
998 converted[pos++] = '@';
999 else
1000 converted[pos++] = *original + 64;
1001 } else
1002 converted[pos++] = *original;
Robert Siemborski53875912000-06-16 04:25:30 +00001003 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001004 converted[pos] = '\0';
Robert Siemborski53875912000-06-16 04:25:30 +00001005
Chris Allegretta4dc03d52002-05-11 03:04:44 +00001006 /* Now, paint the line */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001007 original = fileptr->data;
1008 fileptr->data = converted;
1009 page_start = get_page_start(index);
1010 edit_add(fileptr, line, page_start
1011#ifndef NANO_SMALL
1012 , virt_mark_beginx, virt_cur_x
1013#endif
1014 );
1015 free(converted);
1016 fileptr->data = original;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001017
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001018 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001019 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001020 if (pos > page_start + COLS)
1021 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001022}
1023
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001024/* This function updates current, based on where current_y is;
1025 * reset_cursor() does the opposite. */
1026void update_cursor(void)
1027{
1028 int i = 0;
1029
1030#ifdef DEBUG
1031 fprintf(stderr, _("Moved to (%d, %d) in edit buffer\n"), current_y,
1032 current_x);
1033#endif
1034
1035 current = edittop;
1036 while (i < current_y && current->next != NULL) {
1037 current = current->next;
1038 i++;
1039 }
1040
1041#ifdef DEBUG
1042 fprintf(stderr, _("current->data = \"%s\"\n"), current->data);
1043#endif
1044}
1045
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001046void center_cursor(void)
1047{
1048 current_y = editwinrows / 2;
1049 wmove(edit, current_y, current_x);
1050}
1051
Chris Allegretta6df90f52002-07-19 01:08:59 +00001052/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001053void edit_refresh(void)
1054{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001055 /* Neither of these conditions should occur, but they do. edittop is
1056 * NULL when you open an existing file on the command line, and
1057 * ENABLE_COLOR is defined. Yuck. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001058 if (current == NULL)
1059 return;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001060 if (edittop == NULL)
1061 edittop = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001062
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001063 if (current->lineno >= edittop->lineno + editwinrows)
1064 /* Note that edit_update() changes edittop so that
1065 * current->lineno = edittop->lineno + editwinrows / 2. Thus
1066 * when it then calls edit_refresh(), there is no danger of
1067 * getting an infinite loop. */
Chris Allegrettada721be2000-07-31 01:26:42 +00001068 edit_update(current, CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001069 else {
1070 int nlines = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001071
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001072 /* Don't make the cursor jump around the screen whilst updating */
1073 leaveok(edit, TRUE);
1074
1075 editbot = edittop;
1076 while (nlines < editwinrows) {
1077 update_line(editbot, current_x);
1078 nlines++;
1079 if (editbot->next == NULL)
1080 break;
1081 editbot = editbot->next;
1082 }
1083 while (nlines < editwinrows) {
1084 mvwaddstr(edit, nlines, 0, hblank);
1085 nlines++;
1086 }
1087 /* What the hell are we expecting to update the screen if this
1088 isn't here? Luck?? */
1089 wrefresh(edit);
1090 leaveok(edit, FALSE);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001091 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001092}
1093
1094/*
Chris Allegretta88520c92001-05-05 17:45:54 +00001095 * Same as above, but touch the window first, so everything is redrawn.
Chris Allegrettaf1d33d32000-08-19 03:53:39 +00001096 */
1097void edit_refresh_clearok(void)
1098{
1099 clearok(edit, TRUE);
1100 edit_refresh();
1101 clearok(edit, FALSE);
1102}
1103
1104/*
Chris Allegretta88520c92001-05-05 17:45:54 +00001105 * Nice generic routine to update the edit buffer, given a pointer to the
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001106 * file struct =)
1107 */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001108void edit_update(filestruct *fileptr, topmidbotnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001109{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001110 if (fileptr == NULL)
1111 return;
1112
Chris Allegretta6df90f52002-07-19 01:08:59 +00001113 if (location != TOP) {
1114 int goal = location == NONE ? current_y - 1 : editwinrows / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001115
Chris Allegretta6df90f52002-07-19 01:08:59 +00001116 for (; goal >= 0 && fileptr->prev != NULL; goal--)
1117 fileptr = fileptr->prev;
1118 }
1119 edittop = fileptr;
Robert Siemborski29e9a762000-07-05 03:16:04 +00001120 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001121
1122 edit_refresh();
1123}
1124
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001125/*
1126 * Ask a question on the statusbar. Answer will be stored in answer
1127 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
Chris Allegretta88520c92001-05-05 17:45:54 +00001128 * otherwise, the valid shortcut key caught. Def is any editable text we
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001129 * want to put up by default.
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00001130 *
1131 * New arg tabs tells whether or not to allow tab completion.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001132 */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001133int statusq(int tabs, const shortcut *s, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00001134#ifndef NANO_SMALL
1135 historyheadtype *which_history,
1136#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001137 const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001138{
1139 va_list ap;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001140 char *foo = charalloc(COLS - 3);
Chris Allegretta9caa1932002-02-15 20:08:05 +00001141 int ret;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001142#ifndef DISABLE_TABCOMP
Chris Allegrettaa16e4e92002-01-05 18:59:54 +00001143 int list = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001144#endif
1145
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001146 bottombars(s);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001147
1148 va_start(ap, msg);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001149 vsnprintf(foo, COLS - 4, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001150 va_end(ap);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001151 foo[COLS - 4] = '\0';
Chris Allegretta8ce24132001-04-30 11:28:46 +00001152
Chris Allegretta5beed502003-01-05 20:41:21 +00001153 ret = nanogetstr(tabs, foo, def,
1154#ifndef NANO_SMALL
1155 which_history,
Chris Allegretta2084acc2001-11-29 03:43:08 +00001156#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00001157 s
1158#ifndef DISABLE_TABCOMP
1159 , &list
1160#endif
1161 );
Chris Allegretta6df90f52002-07-19 01:08:59 +00001162 free(foo);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001163
1164 switch (ret) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001165 case NANO_FIRSTLINE_KEY:
1166 do_first_line();
1167 break;
1168 case NANO_LASTLINE_KEY:
1169 do_last_line();
1170 break;
1171 case NANO_CANCEL_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001172 ret = -1;
1173 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001174 default:
Chris Allegretta5b1faac2000-11-16 19:55:30 +00001175 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001176 }
1177
1178#ifdef DEBUG
1179 fprintf(stderr, _("I got \"%s\"\n"), answer);
1180#endif
1181
Chris Allegretta6df90f52002-07-19 01:08:59 +00001182#ifndef DISABLE_TABCOMP
1183 /* if we've done tab completion, there might be a list of
1184 filename matches on the edit window at this point; make sure
1185 they're cleared off */
1186 if (list)
1187 edit_refresh();
1188#endif
1189
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001190 return ret;
1191}
1192
1193/*
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001194 * Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001195 * for N, 2 for All (if all is nonzero when passed in) and -1 for abort
1196 * (^C).
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001197 */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001198int do_yesno(int all, int leavecursor, const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001199{
1200 va_list ap;
1201 char foo[133];
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001202 int kbinput, ok = -1, i;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001203 const char *yesstr; /* String of yes characters accepted */
1204 const char *nostr; /* Same for no */
1205 const char *allstr; /* And all, surprise! */
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001206#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegretta235ab192001-04-12 13:24:40 +00001207 MEVENT mevent;
1208#endif
Chris Allegretta235ab192001-04-12 13:24:40 +00001209
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001210 /* Yes, no and all are strings of any length. Each string consists of
Chris Allegretta598106e2002-01-19 01:59:37 +00001211 all characters accepted as a valid character for that value.
1212 The first value will be the one displayed in the shortcuts. */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001213 yesstr = _("Yy");
1214 nostr = _("Nn");
1215 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001216
1217 /* Write the bottom of the screen */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001218 blank_bottomwin();
Chris Allegretta8ce24132001-04-30 11:28:46 +00001219
Jordi Mallach0b0fc492000-06-23 01:00:13 +00001220 /* Remove gettext call for keybindings until we clear the thing up */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001221 if (!ISSET(NO_HELP)) {
Chris Allegretta6232d662002-05-12 19:52:15 +00001222 char shortstr[3]; /* Temp string for Y, N, A */
1223
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001224 wmove(bottomwin, 1, 0);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001225
Chris Allegretta6232d662002-05-12 19:52:15 +00001226 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001227 onekey(shortstr, _("Yes"), 16);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001228
1229 if (all) {
Chris Allegretta6232d662002-05-12 19:52:15 +00001230 shortstr[1] = allstr[0];
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001231 onekey(shortstr, _("All"), 16);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001232 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001233 wmove(bottomwin, 2, 0);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001234
Chris Allegretta6232d662002-05-12 19:52:15 +00001235 shortstr[1] = nostr[0];
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001236 onekey(shortstr, _("No"), 16);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001237
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001238 onekey("^C", _("Cancel"), 16);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001239 }
1240 va_start(ap, msg);
1241 vsnprintf(foo, 132, msg, ap);
1242 va_end(ap);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001243
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001244 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001245
1246 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001247 mvwaddstr(bottomwin, 0, 0, foo);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001248
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001249 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001250
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001251 wrefresh(bottomwin);
1252
1253 if (leavecursor == 1)
1254 reset_cursor();
1255
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001256 while (ok == -1) {
1257 kbinput = wgetch(edit);
1258
1259 switch (kbinput) {
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001260#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegretta235ab192001-04-12 13:24:40 +00001261 case KEY_MOUSE:
1262
1263 /* Look ma! We get to duplicate lots of code from do_mouse!! */
1264 if (getmouse(&mevent) == ERR)
1265 break;
1266 if (!wenclose(bottomwin, mevent.y, mevent.x) || ISSET(NO_HELP))
1267 break;
1268 mevent.y -= editwinrows + 3;
1269 if (mevent.y < 0)
1270 break;
1271 else {
1272
1273 /* Rather than a bunch of if statements, set up a matrix
Chris Allegretta6df90f52002-07-19 01:08:59 +00001274 of possible return keystrokes based on the x and y
1275 values */
1276 char yesnosquare[2][2];
1277 yesnosquare[0][0] = yesstr[0];
1278 if (all)
1279 yesnosquare[0][1] = allstr[0];
1280 else
1281 yesnosquare[0][1] = '\0';
1282 yesnosquare[1][0] = nostr[0];
1283 yesnosquare[1][1] = NANO_CONTROL_C;
1284 ungetch(yesnosquare[mevent.y][mevent.x / (COLS / 6)]);
Chris Allegretta235ab192001-04-12 13:24:40 +00001285 }
1286 break;
1287#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001288 case NANO_CONTROL_C:
1289 ok = -2;
1290 break;
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001291 default:
1292
Chris Allegretta88520c92001-05-05 17:45:54 +00001293 /* Look for the kbinput in the yes, no and (optimally) all str */
Chris Allegretta598106e2002-01-19 01:59:37 +00001294 for (i = 0; yesstr[i] != 0 && yesstr[i] != kbinput; i++);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001295 if (yesstr[i] != 0) {
Chris Allegrettaea620fe2001-02-18 05:39:41 +00001296 ok = 1;
Chris Allegretta598106e2002-01-19 01:59:37 +00001297 break;
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001298 }
1299
Chris Allegretta598106e2002-01-19 01:59:37 +00001300 for (i = 0; nostr[i] != 0 && nostr[i] != kbinput; i++);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001301 if (nostr[i] != 0) {
1302 ok = 0;
Chris Allegretta598106e2002-01-19 01:59:37 +00001303 break;
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001304 }
1305
1306 if (all) {
Chris Allegretta598106e2002-01-19 01:59:37 +00001307 for (i = 0; allstr[i] != 0 && allstr[i] != kbinput; i++);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001308 if (allstr[i] != 0) {
1309 ok = 2;
Chris Allegretta598106e2002-01-19 01:59:37 +00001310 break;
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001311 }
1312 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001313 }
1314 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001315
1316 /* Then blank the screen */
1317 blank_statusbar_refresh();
1318
1319 if (ok == -2)
1320 return -1;
1321 else
1322 return ok;
1323}
1324
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001325int total_refresh(void)
1326{
1327 clearok(edit, TRUE);
1328 clearok(topwin, TRUE);
1329 clearok(bottomwin, TRUE);
1330 wnoutrefresh(edit);
1331 wnoutrefresh(topwin);
1332 wnoutrefresh(bottomwin);
1333 doupdate();
1334 clearok(edit, FALSE);
1335 clearok(topwin, FALSE);
1336 clearok(bottomwin, FALSE);
1337 edit_refresh();
1338 titlebar(NULL);
1339 return 1;
1340}
1341
1342void display_main_list(void)
1343{
1344 bottombars(main_list);
1345}
1346
Chris Allegretta6df90f52002-07-19 01:08:59 +00001347void statusbar(const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001348{
1349 va_list ap;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001350 char *foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001351 int start_x = 0;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001352 size_t foo_len;
1353
1354 assert(COLS >= 4);
1355 foo = charalloc(COLS - 3);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001356
1357 va_start(ap, msg);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001358 vsnprintf(foo, COLS - 3, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001359 va_end(ap);
1360
Chris Allegretta6df90f52002-07-19 01:08:59 +00001361 foo[COLS - 4] = '\0';
1362 foo_len = strlen(foo);
1363 start_x = (COLS - foo_len - 4) / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001364
1365 /* Blank out line */
1366 blank_statusbar();
1367
1368 wmove(bottomwin, 0, start_x);
1369
1370 wattron(bottomwin, A_REVERSE);
1371
1372 waddstr(bottomwin, "[ ");
1373 waddstr(bottomwin, foo);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001374 free(foo);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001375 waddstr(bottomwin, " ]");
Chris Allegretta8ce24132001-04-30 11:28:46 +00001376
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001377 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001378
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001379 wrefresh(bottomwin);
1380
1381 if (ISSET(CONSTUPDATE))
1382 statblank = 1;
1383 else
1384 statblank = 25;
1385}
1386
Chris Allegretta2084acc2001-11-29 03:43:08 +00001387int do_cursorpos(int constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001388{
1389 filestruct *fileptr;
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001390 float linepct = 0.0, bytepct = 0.0, colpct = 0.0;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00001391 long i = 0, j = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001392 static long old_i = -1, old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001393
1394 if (current == NULL || fileage == NULL)
1395 return 0;
1396
Chris Allegretta2084acc2001-11-29 03:43:08 +00001397 if (old_i == -1)
1398 old_i = i;
1399
1400 if (old_totsize == -1)
1401 old_totsize = totsize;
1402
Chris Allegretta6df90f52002-07-19 01:08:59 +00001403 colpct = 100 * (xplustabs() + 1) / (strlenpt(current->data) + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001404
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001405 for (fileptr = fileage; fileptr != current && fileptr != NULL;
1406 fileptr = fileptr->next)
1407 i += strlen(fileptr->data) + 1;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00001408
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001409 if (fileptr == NULL)
1410 return -1;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00001411
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001412 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00001413
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001414 j = totsize;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00001415
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001416 if (totsize > 0)
1417 bytepct = 100 * i / totsize;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00001418
1419 if (totlines > 0)
1420 linepct = 100 * current->lineno / totlines;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001421
1422#ifdef DEBUG
1423 fprintf(stderr, _("do_cursorpos: linepct = %f, bytepct = %f\n"),
1424 linepct, bytepct);
1425#endif
1426
Chris Allegretta2084acc2001-11-29 03:43:08 +00001427 /* if constant is zero, display the position on the statusbar
1428 unconditionally; otherwise, only display the position when the
1429 character values have changed */
1430 if (!constant || (old_i != i || old_totsize != totsize)) {
Chris Allegretta598106e2002-01-19 01:59:37 +00001431 statusbar(_
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001432 ("line %d/%d (%.0f%%), col %ld/%ld (%.0f%%), char %ld/%ld (%.0f%%)"),
Chris Allegrettaf3a07b22002-03-29 15:15:38 +00001433 current->lineno, totlines, linepct, xplustabs() + 1,
Chris Allegretta6df90f52002-07-19 01:08:59 +00001434 strlenpt(current->data) + 1, colpct, i, j, bytepct);
Chris Allegretta2084acc2001-11-29 03:43:08 +00001435 }
1436
1437 old_i = i;
1438 old_totsize = totsize;
1439
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001440 reset_cursor();
1441 return 1;
1442}
1443
Chris Allegretta2084acc2001-11-29 03:43:08 +00001444int do_cursorpos_void(void)
1445{
1446 return do_cursorpos(0);
1447}
1448
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001449/* Our shortcut-list-compliant help function, which is
1450 * better than nothing, and dynamic! */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001451int do_help(void)
1452{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001453#ifndef DISABLE_HELP
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001454 int i, j, row = 0, page = 1, kbinput = 0, no_more = 0, kp, kp2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001455 int no_help_flag = 0;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001456 const shortcut *oldshortcut;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001457
1458 blank_edit();
1459 curs_set(0);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001460 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001461 blank_statusbar();
1462
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001463 /* set help_text as the string to display */
Chris Allegrettab3655b42001-10-22 03:15:31 +00001464 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001465 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001466
1467 oldshortcut = currshortcut;
Chris Allegrettab3655b42001-10-22 03:15:31 +00001468
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001469 currshortcut = help_list;
Chris Allegretta6fe61492001-05-21 12:56:25 +00001470
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001471 kp = keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001472 kp2 = keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001473
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001474 if (ISSET(NO_HELP)) {
1475
Chris Allegretta88520c92001-05-05 17:45:54 +00001476 /* Well, if we're going to do this, we should at least
Chris Allegretta70444892001-01-07 23:02:02 +00001477 do it the right way */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001478 no_help_flag = 1;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001479 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00001480 window_init();
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001481 bottombars(help_list);
Chris Allegretta70444892001-01-07 23:02:02 +00001482
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001483 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001484 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001485
1486 do {
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001487 const char *ptr = help_text;
1488
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001489 switch (kbinput) {
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001490#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegretta598106e2002-01-19 01:59:37 +00001491 case KEY_MOUSE:
1492 do_mouse();
1493 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001494#endif
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001495 case 27:
1496 kbinput = wgetch(edit);
1497 switch(kbinput) {
1498 case '[':
1499 kbinput = wgetch(edit);
1500 switch(kbinput) {
1501 case '5': /* Alt-[-5 = Page Up */
1502 wgetch(edit);
1503 goto do_pageupkey;
1504 break;
1505 case 'V': /* Alt-[-V = Page Up in Hurd Console */
1506 case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
1507 goto do_pageupkey;
1508 break;
1509 case '6': /* Alt-[-6 = Page Down */
1510 wgetch(edit);
1511 goto do_pagedownkey;
1512 break;
1513 case 'U': /* Alt-[-U = Page Down in Hurd Console */
1514 case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
1515 goto do_pagedownkey;
1516 break;
1517 }
1518 break;
1519 }
1520 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001521 case NANO_NEXTPAGE_KEY:
1522 case NANO_NEXTPAGE_FKEY:
1523 case KEY_NPAGE:
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001524 do_pagedownkey:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001525 if (!no_more) {
1526 blank_edit();
1527 page++;
1528 }
1529 break;
1530 case NANO_PREVPAGE_KEY:
1531 case NANO_PREVPAGE_FKEY:
1532 case KEY_PPAGE:
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001533 do_pageupkey:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001534 if (page > 1) {
1535 no_more = 0;
1536 blank_edit();
1537 page--;
1538 }
1539 break;
1540 }
1541
Chris Allegretta88520c92001-05-05 17:45:54 +00001542 /* Calculate where in the text we should be, based on the page */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001543 for (i = 1; i < page; i++) {
1544 row = 0;
1545 j = 0;
Chris Allegretta44e73df2000-09-07 03:37:38 +00001546
1547 while (row < editwinrows - 2 && *ptr != '\0') {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001548 if (*ptr == '\n' || j == COLS - 5) {
1549 j = 0;
1550 row++;
1551 }
1552 ptr++;
1553 j++;
1554 }
1555 }
1556
1557 i = 0;
1558 j = 0;
1559 while (i < editwinrows && *ptr != '\0') {
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001560 const char *end = ptr;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001561 while (*end != '\n' && *end != '\0' && j != COLS - 5) {
1562 end++;
1563 j++;
1564 }
1565 if (j == COLS - 5) {
1566
Chris Allegretta88520c92001-05-05 17:45:54 +00001567 /* Don't print half a word if we've run out of space */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001568 while (*end != ' ' && *end != '\0') {
1569 end--;
1570 j--;
1571 }
1572 }
1573 mvwaddnstr(edit, i, 0, ptr, j);
1574 j = 0;
1575 i++;
1576 if (*end == '\n')
1577 end++;
1578 ptr = end;
1579 }
1580 if (*ptr == '\0') {
1581 no_more = 1;
1582 continue;
1583 }
Chris Allegretta598106e2002-01-19 01:59:37 +00001584 } while ((kbinput = wgetch(edit)) != NANO_EXIT_KEY &&
1585 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00001586
Chris Allegrettab3655b42001-10-22 03:15:31 +00001587 currshortcut = oldshortcut;
Chris Allegrettab3655b42001-10-22 03:15:31 +00001588
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001589 if (no_help_flag) {
Chris Allegretta70444892001-01-07 23:02:02 +00001590 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001591 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001592 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00001593 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00001594 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001595 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001596
1597 curs_set(1);
1598 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001599 kp = keypad_on(edit, kp);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001600 kp2 = keypad_on(bottomwin, kp2);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001601
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001602 /* The help_init() at the beginning allocated help_text, which has
1603 now been written to screen. */
1604 free(help_text);
1605 help_text = NULL;
1606
Chris Allegretta6df90f52002-07-19 01:08:59 +00001607#elif defined(DISABLE_HELP)
1608 nano_disabled_msg();
1609#endif
1610
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001611 return 1;
1612}
1613
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001614int keypad_on(WINDOW *win, int newval)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001615{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001616/* This is taken right from aumix. Don't sue me. */
1617#ifdef HAVE_USEKEYPAD
1618 int old = win->_use_keypad;
1619 keypad(win, newval);
1620 return old;
1621#else
1622 keypad(win, newval);
1623 return 1;
1624#endif /* HAVE_USEKEYPAD */
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001625}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001626
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001627/* Highlight the current word being replaced or spell checked. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001628void do_replace_highlight(int highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00001629{
1630 char *highlight_word = NULL;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001631 int x, y, word_len;
Chris Allegrettafb62f732000-12-05 11:36:41 +00001632
Chris Allegretta598106e2002-01-19 01:59:37 +00001633 highlight_word =
1634 mallocstrcpy(highlight_word, &current->data[current_x]);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001635
1636#ifdef HAVE_REGEX_H
1637 if (ISSET(USE_REGEXP))
1638 /* if we're using regexps, the highlight is the length of the
1639 search result, not the length of the regexp string */
1640 word_len = regmatches[0].rm_eo - regmatches[0].rm_so;
1641 else
1642#endif
1643 word_len = strlen(word);
1644
1645 highlight_word[word_len] = '\0';
Chris Allegrettafb62f732000-12-05 11:36:41 +00001646
Chris Allegretta88520c92001-05-05 17:45:54 +00001647 /* adjust output when word extends beyond screen */
Chris Allegrettafb62f732000-12-05 11:36:41 +00001648
1649 x = xplustabs();
Chris Allegretta6df90f52002-07-19 01:08:59 +00001650 y = get_page_start(x) + COLS;
Chris Allegrettafb62f732000-12-05 11:36:41 +00001651
Chris Allegretta6df90f52002-07-19 01:08:59 +00001652 if ((COLS - (y - x) + word_len) > COLS) {
Chris Allegrettafb62f732000-12-05 11:36:41 +00001653 highlight_word[y - x - 1] = '$';
1654 highlight_word[y - x] = '\0';
1655 }
1656
1657 /* OK display the output */
1658
1659 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00001660
Chris Allegrettafb62f732000-12-05 11:36:41 +00001661 if (highlight_flag)
1662 wattron(edit, A_REVERSE);
1663
1664 waddstr(edit, highlight_word);
1665
1666 if (highlight_flag)
1667 wattroff(edit, A_REVERSE);
1668
1669 free(highlight_word);
1670}
1671
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001672/* Fix editbot, based on the assumption that edittop is correct. */
1673void fix_editbot(void)
1674{
1675 int i;
1676
1677 editbot = edittop;
1678 for (i = 0; i < editwinrows && editbot->next != NULL; i++)
1679 editbot = editbot->next;
1680}
1681
1682#ifdef DEBUG
1683/* Dump the current file structure to stderr */
1684void dump_buffer(const filestruct *inptr) {
1685 if (inptr == fileage)
1686 fprintf(stderr, _("Dumping file buffer to stderr...\n"));
1687 else if (inptr == cutbuffer)
1688 fprintf(stderr, _("Dumping cutbuffer to stderr...\n"));
1689 else
1690 fprintf(stderr, _("Dumping a buffer to stderr...\n"));
1691
1692 while (inptr != NULL) {
1693 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
1694 inptr = inptr->next;
1695 }
1696}
1697#endif /* DEBUG */
1698
1699#ifdef DEBUG
1700void dump_buffer_reverse(void) {
1701 const filestruct *fileptr = filebot;
1702
1703 while (fileptr != NULL) {
1704 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
1705 fileptr = fileptr->prev;
1706 }
1707}
1708#endif /* DEBUG */
1709
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001710#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00001711#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001712#define XLCREDIT_LEN 8
1713
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001714void do_credits(void)
1715{
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001716 int i, j = 0, k, place = 0, start_x;
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001717
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +00001718 const char *what;
1719 const char *xlcredits[XLCREDIT_LEN];
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001720
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +00001721 const char *credits[CREDIT_LEN] = {
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001722 "0", /* "The nano text editor" */
1723 "1", /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001724 VERSION,
1725 "",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001726 "2", /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001727 "Chris Allegretta",
1728 "Jordi Mallach",
1729 "Adam Rogoyski",
1730 "Rob Siemborski",
1731 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001732 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00001733 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00001734 "Ken Tyler",
1735 "Sven Guckes",
1736 "Florian König",
1737 "Pauli Virtanen",
1738 "Daniele Medri",
1739 "Clement Laforet",
1740 "Tedi Heriyanto",
1741 "Bill Soudan",
1742 "Christian Weisgerber",
1743 "Erik Andersen",
1744 "Big Gaute",
1745 "Joshua Jensen",
1746 "Ryan Krebs",
1747 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00001748 "",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001749 "3", /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001750 "Plattsburgh State University",
1751 "Benet Laboratories",
1752 "Amy Allegretta",
1753 "Linda Young",
1754 "Jeremy Robichaud",
1755 "Richard Kolb II",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001756 "4", /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001757 "Linus Torvalds",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001758 "5", /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00001759 "Thomas Dickey",
1760 "Pavel Curtis",
1761 "Zeyd Ben-Halim",
1762 "Eric S. Raymond",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001763 "6", /* "and anyone else we forgot..." */
1764 "7", /* "Thank you for using nano!\n" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001765 "", "", "", "",
1766 "(c) 1999-2002 Chris Allegretta",
1767 "", "", "", "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00001768 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001769 };
1770
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001771 xlcredits[0] = _("The nano text editor");
1772 xlcredits[1] = _("version ");
1773 xlcredits[2] = _("Brought to you by:");
1774 xlcredits[3] = _("Special thanks to:");
1775 xlcredits[4] = _("The Free Software Foundation");
1776 xlcredits[5] = _("For ncurses:");
1777 xlcredits[6] = _("and anyone else we forgot...");
1778 xlcredits[7] = _("Thank you for using nano!\n");
1779
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001780 curs_set(0);
1781 nodelay(edit, TRUE);
1782 blank_bottombars();
1783 mvwaddstr(topwin, 0, 0, hblank);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001784 blank_edit();
1785 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001786 wrefresh(bottomwin);
1787 wrefresh(topwin);
1788
1789 while (wgetch(edit) == ERR) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001790 for (k = 0; k <= 1; k++) {
1791 blank_edit();
Chris Allegretta598106e2002-01-19 01:59:37 +00001792 for (i = editwinrows / 2 - 1; i >= (editwinrows / 2 - 1 - j);
1793 i--) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001794 mvwaddstr(edit, i * 2 - k, 0, hblank);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001795
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001796 if (place - (editwinrows / 2 - 1 - i) < CREDIT_LEN) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001797 what = credits[place - (editwinrows / 2 - 1 - i)];
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001798
1799 /* God I've missed hacking. If what is exactly
1800 1 char long, it's a sentinel for a translated
1801 string, so use that instead. This means no
1802 thanking people with 1 character long names ;-) */
1803 if (strlen(what) == 1)
1804 what = xlcredits[atoi(what)];
1805 } else
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001806 what = "";
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001807
Chris Allegretta17dcb722001-01-20 21:40:07 +00001808 start_x = COLS / 2 - strlen(what) / 2 - 1;
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001809 mvwaddstr(edit, i * 2 - k, start_x, what);
1810 }
1811 usleep(700000);
1812 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001813 }
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001814 if (j < editwinrows / 2 - 1)
1815 j++;
1816
1817 place++;
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001818
1819 if (place >= CREDIT_LEN + editwinrows / 2)
1820 break;
1821 }
1822
1823 nodelay(edit, FALSE);
1824 curs_set(1);
1825 display_main_list();
1826 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00001827}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001828#endif