blob: c699128a47909e69f62b82129cdacf24ddd505de [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
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
Jordi Mallachf9390af2003-08-05 19:31:12 +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 Allegretta7662c862003-01-13 01:35:15 +0000164/* Repaint the statusbar when getting a character in nanogetstr(). buf
Chris Allegretta6df90f52002-07-19 01:08:59 +0000165 * should be no longer than COLS - 4.
166 *
Chris Allegretta7662c862003-01-13 01:35:15 +0000167 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +0000168 * off! */
Chris Allegrettaf717f982003-02-13 22:25:01 +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(). */
Chris Allegrettaf717f982003-02-13 22:25:01 +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
Chris Allegretta65f075d2003-02-13 03:03:49 +0000197 )
Chris Allegretta6df90f52002-07-19 01:08:59 +0000198{
199 int kbinput;
Chris Allegretta09fc4302003-01-16 22:16:38 +0000200 static int x = -1;
Chris Allegretta6df90f52002-07-19 01:08:59 +0000201 /* 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;
Chris Allegretta8031f832003-01-09 05:29:58 +0000211 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +0000212 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000213 int last_kbinput = 0;
214
215 /* This variable is used in the search history code. use_cb == 0
216 means that we're using the existing history and ignoring
217 currentbuf. use_cb == 1 means that the entry in answer should be
218 moved to currentbuf or restored from currentbuf to answer.
219 use_cb == 2 means that the entry in currentbuf should be moved to
220 answer or restored from answer to currentbuf. */
221 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +0000222#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +0000223 xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +0000224
225 /* Only put x at the end of the string if it's uninitialized or if
226 it would be past the end of the string as it is. Otherwise,
227 leave it alone. This is so the cursor position stays at the same
228 place if a prompt-changing toggle is pressed. */
Chris Allegretta65f075d2003-02-13 03:03:49 +0000229 if (x == -1 || x > xend || resetstatuspos)
Chris Allegretta09fc4302003-01-16 22:16:38 +0000230 x = xend;
231
Chris Allegrettae1e0fd62003-04-15 01:15:09 +0000232 answer = charealloc(answer, xend + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000233 if (xend > 0)
234 strcpy(answer, def);
235 else
236 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000237
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000238#if !defined(DISABLE_HELP) || (!defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION))
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000239 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +0000240#endif
241
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000242 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +0000243
Chris Allegretta6df90f52002-07-19 01:08:59 +0000244 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000245
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000246 /* Make sure any editor screen updates are displayed before getting
247 input */
Chris Allegretta022b96f2000-11-14 17:47:58 +0000248 wrefresh(edit);
249
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000250 while ((kbinput = wgetch(bottomwin)) != 13) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000251 for (t = s; t != NULL; t = t->next) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000252#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +0000253 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000254#endif
255
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000256 if (kbinput == t->val && kbinput < 32) {
Chris Allegretta5bf51d32000-11-16 06:01:10 +0000257
Chris Allegrettab3655b42001-10-22 03:15:31 +0000258#ifndef DISABLE_HELP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000259 /* Have to do this here, it would be too late to do it
260 in statusq() */
Chris Allegretta598106e2002-01-19 01:59:37 +0000261 if (kbinput == NANO_HELP_KEY || kbinput == NANO_HELP_FKEY) {
Chris Allegrettab3655b42001-10-22 03:15:31 +0000262 do_help();
263 break;
264 }
265#endif
Chris Allegretta5af58892003-01-17 21:07:38 +0000266
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000267 return t->val;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000268 }
269 }
Chris Allegretta6df90f52002-07-19 01:08:59 +0000270 assert(0 <= x && x <= xend && xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000271
Chris Allegretta04d848e2000-11-05 17:54:41 +0000272 if (kbinput != '\t')
273 tabbed = 0;
274
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000275 switch (kbinput) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000276
Chris Allegretta598106e2002-01-19 01:59:37 +0000277 /* Stuff we want to equate with <enter>, ASCII 13 */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000278 case 343:
Chris Allegrettaf9b6c9b2000-10-18 19:35:59 +0000279 ungetch(13); /* Enter on iris-ansi $TERM, sometimes */
280 break;
Chris Allegretta598106e2002-01-19 01:59:37 +0000281 /* Stuff we want to ignore */
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000282#ifdef PDCURSES
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000283 case 541:
284 case 542:
Chris Allegretta598106e2002-01-19 01:59:37 +0000285 case 543: /* Right ctrl again */
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000286 case 544:
Chris Allegretta598106e2002-01-19 01:59:37 +0000287 case 545: /* Right alt again */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000288 break;
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000289#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000290#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000291 case KEY_MOUSE:
292 do_mouse();
293 break;
294#endif
Chris Allegretta658399a2001-06-14 02:54:22 +0000295 case NANO_HOME_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000296 case KEY_HOME:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000297 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000298 break;
Chris Allegretta658399a2001-06-14 02:54:22 +0000299 case NANO_END_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000300 case KEY_END:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000301 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000302 break;
303 case KEY_RIGHT:
Chris Allegretta35dac582001-03-21 15:07:20 +0000304 case NANO_FORWARD_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000305 if (x < xend)
306 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000307 break;
308 case NANO_CONTROL_D:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000309 if (x < xend) {
310 memmove(answer + x, answer + x + 1, xend - x);
311 xend--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000312 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000313 break;
314 case NANO_CONTROL_K:
315 case NANO_CONTROL_U:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000316 null_at(&answer, 0);
317 xend = 0;
318 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000319 break;
320 case KEY_BACKSPACE:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000321 case 127:
322 case NANO_CONTROL_H:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000323 if (x > 0) {
324 memmove(answer + x - 1, answer + x, xend - x + 1);
Chris Allegretta04d848e2000-11-05 17:54:41 +0000325 x--;
Chris Allegretta6df90f52002-07-19 01:08:59 +0000326 xend--;
327 }
Chris Allegretta04d848e2000-11-05 17:54:41 +0000328 break;
329 case NANO_CONTROL_I:
Chris Allegretta5beed502003-01-05 20:41:21 +0000330#ifndef NANO_SMALL
331 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +0000332 if (history_list != NULL) {
333 if (!complete || last_kbinput != NANO_CONTROL_I) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000334 history_list->current = (historytype *)history_list;
335 history_list->len = strlen(answer);
336 }
Chris Allegretta6df90f52002-07-19 01:08:59 +0000337
Chris Allegretta7662c862003-01-13 01:35:15 +0000338 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000339 complete = get_history_completion(history_list, answer);
340 xend = strlen(complete);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000341 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +0000342 answer = mallocstrcpy(answer, complete);
343 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000344 }
Chris Allegretta5beed502003-01-05 20:41:21 +0000345#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +0000346 else
347#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +0000348#endif
Chris Allegretta5beed502003-01-05 20:41:21 +0000349#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +0000350 if (allowtabs) {
351 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +0000352
Chris Allegretta327abda2003-01-17 05:04:17 +0000353 answer = input_tab(answer, x, &tabbed, &shift, list);
354 xend = strlen(answer);
355 x += shift;
356 if (x > xend)
357 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +0000358 }
359#endif
360 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000361 case KEY_LEFT:
Chris Allegretta35dac582001-03-21 15:07:20 +0000362 case NANO_BACK_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000363 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000364 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000365 break;
366 case KEY_UP:
Chris Allegretta7662c862003-01-13 01:35:15 +0000367 case NANO_UP_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +0000368#ifndef NANO_SMALL
Chris Allegretta4b376a42003-04-16 02:08:23 +0000369 do_upkey:
Chris Allegretta09fc4302003-01-16 22:16:38 +0000370 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +0000371
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000372 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
373 isn't NULL, and currentbuf is different from answer,
374 it means that we're scrolling up at the top of the
375 search history, and we need to save the current
376 answer in currentbuf; do this and reset use_cb to
377 0 */
378 if (currentbuf == NULL || (use_cb == 1 && strcmp(currentbuf, answer))) {
Chris Allegretta8031f832003-01-09 05:29:58 +0000379 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000380 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +0000381 }
382
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000383 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
384 is different from answer, it means that we're
385 scrolling up at the bottom of the search history, and
386 we need to make the string in currentbuf the current
387 answer; do this, blow away currentbuf since we don't
388 need it anymore, and reset use_cb to 0 */
389 if (currentbuf != NULL && use_cb == 2 && strcmp(currentbuf, answer)) {
390 answer = mallocstrcpy(answer, currentbuf);
391 free(currentbuf);
392 currentbuf = NULL;
393 xend = strlen(answer);
394 use_cb = 0;
395
396 /* else get older search from the history list and save
397 it in answer; if there is no older search, blank out
398 answer */
399 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000400 answer = mallocstrcpy(answer, history);
401 xend = strlen(history);
402 } else {
403 answer = mallocstrcpy(answer, "");
404 xend = 0;
405 }
406 x = xend;
407 }
Chris Allegretta5beed502003-01-05 20:41:21 +0000408#endif
Chris Allegretta54abd942003-01-09 23:43:12 +0000409 break;
Chris Allegretta5beed502003-01-05 20:41:21 +0000410 case KEY_DOWN:
Chris Allegretta7662c862003-01-13 01:35:15 +0000411 case NANO_DOWN_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +0000412#ifndef NANO_SMALL
Chris Allegretta4b376a42003-04-16 02:08:23 +0000413 do_downkey:
Chris Allegretta09fc4302003-01-16 22:16:38 +0000414 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000415
416 /* get newer search from the history list and save it
417 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +0000418 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000419 answer = mallocstrcpy(answer, history);
420 xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +0000421
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000422 /* if there is no newer search, we're here */
423
424 /* if currentbuf isn't NULL and use_cb isn't 2, it means
425 that we're scrolling down at the bottom of the search
426 history and we need to make the string in currentbuf
427 the current answer; do this, blow away currentbuf
428 since we don't need it anymore, and set use_cb to
429 1 */
430 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +0000431 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +0000432 free(currentbuf);
433 currentbuf = NULL;
434 xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000435 use_cb = 1;
436
437 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
438 it means that we're scrolling down at the bottom of
439 the search history and the current answer needs to be
440 saved in currentbuf; do this, blank out answer, and
441 set use_cb to 2 */
442 } else if (use_cb != 2) {
443 currentbuf = mallocstrcpy(currentbuf, answer);
Chris Allegretta5beed502003-01-05 20:41:21 +0000444 answer = mallocstrcpy(answer, "");
445 xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000446 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +0000447 }
448 x = xend;
449 }
450#endif
451 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000452 case KEY_DC:
453 goto do_deletekey;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000454 case 27:
455 switch (kbinput = wgetch(edit)) {
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000456 case 'O':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000457 switch (kbinput = wgetch(edit)) {
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000458 case 'F':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000459 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000460 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000461 case 'H':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000462 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000463 break;
464 }
465 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000466 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000467 switch (kbinput = wgetch(edit)) {
Chris Allegretta4b376a42003-04-16 02:08:23 +0000468 case 'A':
469#ifndef NANO_SMALL
470 goto do_upkey;
471#else
472 break;
473#endif
474 case 'B':
475#ifndef NANO_SMALL
476 goto do_downkey;
477#else
478 break;
479#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000480 case 'C':
481 if (x < xend)
482 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000483 break;
484 case 'D':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000485 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000486 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000487 break;
Chris Allegretta13f094e2003-08-04 00:59:27 +0000488 case 'F':
Chris Allegretta653d6142003-08-04 02:12:03 +0000489 x = xend;
Chris Allegretta13f094e2003-08-04 00:59:27 +0000490 break;
491 case 'H':
Chris Allegretta653d6142003-08-04 02:12:03 +0000492 x = 0;
Chris Allegretta13f094e2003-08-04 00:59:27 +0000493 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000494 case '1':
495 case '7':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000496 x = 0;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000497 goto skip_tilde;
498 case '3':
499 do_deletekey:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000500 if (x < xend) {
501 memmove(answer + x, answer + x + 1, xend - x);
502 xend--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000503 }
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000504 goto skip_tilde;
505 case '4':
506 case '8':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000507 x = xend;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000508 skip_tilde:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000509 nodelay(edit, TRUE);
510 kbinput = wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000511 if (kbinput == '~' || kbinput == ERR)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000512 kbinput = -1;
513 nodelay(edit, FALSE);
514 break;
515 }
Chris Allegretta6df90f52002-07-19 01:08:59 +0000516 break;
Chris Allegretta658399a2001-06-14 02:54:22 +0000517 default:
518
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000519 for (t = s; t != NULL; t = t->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +0000520#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +0000521 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
Chris Allegretta598106e2002-01-19 01:59:37 +0000522 kbinput);
Chris Allegretta658399a2001-06-14 02:54:22 +0000523#endif
Chris Allegretta5af58892003-01-17 21:07:38 +0000524 if (kbinput == t->val || kbinput == t->val - 32)
525 /* We hit an Alt key. Do like above. We don't
526 just ungetch() the letter and let it get
527 caught above cause that screws the
528 keypad... */
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000529 return t->val;
Chris Allegretta658399a2001-06-14 02:54:22 +0000530 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000531 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000532 break;
533
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000534 default:
535 if (kbinput < 32)
536 break;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +0000537 answer = charealloc(answer, xend + 2);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000538 memmove(answer + x + 1, answer + x, xend - x + 1);
539 xend++;
540 answer[x] = kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000541 x++;
542
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000543#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +0000544 fprintf(stderr, "input \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000545#endif
Chris Allegretta5beed502003-01-05 20:41:21 +0000546 } /* switch (kbinput) */
Chris Allegrettaa65ba512003-01-05 20:57:07 +0000547#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +0000548 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +0000549#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +0000550 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000551 wrefresh(bottomwin);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000552 } /* while (kbinput ...) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000553
Chris Allegretta5af58892003-01-17 21:07:38 +0000554 /* We finished putting in an answer; reset x */
555 x = -1;
556
Chris Allegretta7662c862003-01-13 01:35:15 +0000557 /* Just check for a blank answer here */
Chris Allegretta15c28f82003-01-05 21:47:06 +0000558 if (answer[0] == '\0')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000559 return -2;
560 else
561 return 0;
562}
563
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000564/* If modified is not already set, set it and update titlebar. */
565void set_modified(void)
566{
567 if (!ISSET(MODIFIED)) {
568 SET(MODIFIED);
569 titlebar(NULL);
570 wrefresh(topwin);
571 }
572}
573
Chris Allegrettaf717f982003-02-13 22:25:01 +0000574void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000575{
576 int namelen, space;
Chris Allegrettaf717f982003-02-13 22:25:01 +0000577 const char *what = path;
Chris Allegrettaf4b96012001-01-03 07:11:47 +0000578
579 if (path == NULL)
580 what = filename;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000581
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000582 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +0000583
Chris Allegretta6df90f52002-07-19 01:08:59 +0000584 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyc5967552002-06-21 03:20:06 +0000585 mvwaddnstr(topwin, 0, 2, VERMSG, COLS - 3);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000586
Chris Allegretta6df90f52002-07-19 01:08:59 +0000587 space = COLS - sizeof(VERMSG) - 22;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000588
Chris Allegrettaf4b96012001-01-03 07:11:47 +0000589 namelen = strlen(what);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000590
David Lawrence Ramseyc5967552002-06-21 03:20:06 +0000591 if (space > 0) {
592 if (what[0] == '\0')
Chris Allegretta6df90f52002-07-19 01:08:59 +0000593 mvwaddnstr(topwin, 0, COLS / 2 - 6, _("New Buffer"),
594 COLS / 2 + COLS % 2 - 6);
595 else if (namelen > space) {
596 if (path == NULL)
597 waddstr(topwin, _(" File: ..."));
598 else
599 waddstr(topwin, _(" DIR: ..."));
600 waddstr(topwin, &what[namelen - space]);
601 } else {
602 if (path == NULL)
603 mvwaddstr(topwin, 0, COLS / 2 - (namelen / 2 + 1),
604 _("File: "));
605 else
606 mvwaddstr(topwin, 0, COLS / 2 - (namelen / 2 + 1),
607 _(" DIR: "));
608 waddstr(topwin, what);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000609 }
David Lawrence Ramseyc5967552002-06-21 03:20:06 +0000610 } /* If we don't have space, we shouldn't bother */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000611 if (ISSET(MODIFIED))
Chris Allegretta6df90f52002-07-19 01:08:59 +0000612 mvwaddnstr(topwin, 0, COLS - 11, _(" Modified "), 11);
Chris Allegretta4dc03d52002-05-11 03:04:44 +0000613 else if (ISSET(VIEW_MODE))
Chris Allegretta6df90f52002-07-19 01:08:59 +0000614 mvwaddnstr(topwin, 0, COLS - 11, _(" View "), 11);
Chris Allegretta8ce24132001-04-30 11:28:46 +0000615
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000616 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +0000617
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000618 wrefresh(topwin);
619 reset_cursor();
620}
621
Chris Allegretta6232d662002-05-12 19:52:15 +0000622void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000623{
Chris Allegrettabc72e362002-02-16 20:03:44 +0000624 int i, j, numcols;
Chris Allegretta3bbc4162003-01-23 00:46:12 +0000625 char keystr[9];
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000626 int slen;
627
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000628 if (ISSET(NO_HELP))
629 return;
630
Chris Allegretta6232d662002-05-12 19:52:15 +0000631 if (s == main_list) {
632 slen = MAIN_VISIBLE;
633 assert(MAIN_VISIBLE <= length_of_list(s));
634 } else
635 slen = length_of_list(s);
636
Chris Allegretta6232d662002-05-12 19:52:15 +0000637 /* There will be this many columns of shortcuts */
638 numcols = (slen + (slen % 2)) / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000639
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000640 blank_bottomwin();
Chris Allegretta658399a2001-06-14 02:54:22 +0000641
Chris Allegrettabc72e362002-02-16 20:03:44 +0000642 for (i = 0; i < numcols; i++) {
643 for (j = 0; j <= 1; j++) {
Chris Allegretta658399a2001-06-14 02:54:22 +0000644
Chris Allegretta6232d662002-05-12 19:52:15 +0000645 wmove(bottomwin, 1 + j, i * (COLS / numcols));
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000646
Chris Allegretta5beed502003-01-05 20:41:21 +0000647 /* Yucky sentinel values we can't handle a better way */
Chris Allegretta6232d662002-05-12 19:52:15 +0000648 if (s->val == NANO_CONTROL_SPACE)
649 strcpy(keystr, "^ ");
Chris Allegrettaa65ba512003-01-05 20:57:07 +0000650#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +0000651 else if (s->val == KEY_UP)
Chris Allegretta3bbc4162003-01-23 00:46:12 +0000652 strncpy(keystr, _("Up"), 8);
Chris Allegretta5beed502003-01-05 20:41:21 +0000653#endif /* NANO_SMALL */
654 else if (s->val > 0) {
Chris Allegretta6232d662002-05-12 19:52:15 +0000655 if (s->val < 64)
656 sprintf(keystr, "^%c", s->val + 64);
657 else
658 sprintf(keystr, "M-%c", s->val - 32);
659 } else if (s->altval > 0)
660 sprintf(keystr, "M-%c", s->altval);
Chris Allegretta658399a2001-06-14 02:54:22 +0000661
Chris Allegretta6232d662002-05-12 19:52:15 +0000662 onekey(keystr, s->desc, COLS / numcols);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000663
Chris Allegretta6232d662002-05-12 19:52:15 +0000664 s = s->next;
665 if (s == NULL)
666 goto break_completely_out;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000667 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000668 }
669
Chris Allegretta6df90f52002-07-19 01:08:59 +0000670 break_completely_out:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000671 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000672}
673
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000674/* Write a shortcut key to the help area at the bottom of the window.
675 * keystroke is e.g. "^G" and desc is e.g. "Get Help".
676 * We are careful to write exactly len characters, even if len is
677 * very small and keystroke and desc are long. */
Chris Allegrettaf717f982003-02-13 22:25:01 +0000678void onekey(const char *keystroke, const char *desc, int len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000679{
Chris Allegretta5beed502003-01-05 20:41:21 +0000680
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000681 wattron(bottomwin, A_REVERSE);
682 waddnstr(bottomwin, keystroke, len);
683 wattroff(bottomwin, A_REVERSE);
684 len -= strlen(keystroke);
685 if (len > 0) {
686 waddch(bottomwin, ' ');
687 len--;
688 waddnstr(bottomwin, desc, len);
689 len -= strlen(desc);
690 for (; len > 0; len--)
691 waddch(bottomwin, ' ');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000692 }
693}
694
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000695/* And so start the display update routines. */
696
697#ifndef NDEBUG
698int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000699{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000700 int check_line = 0;
701 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000702
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000703 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
704 check_line++;
705 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000706}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000707#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +0000708
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000709 /* nano scrolls horizontally within a line in chunks. This function
710 * returns the column number of the first character displayed in the
711 * window when the cursor is at the given column. */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000712int get_page_start(int column)
Chris Allegretta6df90f52002-07-19 01:08:59 +0000713{
714 assert(COLS > 9);
715 return column < COLS - 1 ? 0 : column - 7 - (column - 8) % (COLS - 9);
716}
717
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000718/* Resets current_y, based on the position of current, and puts the
719 * cursor at (current_y, current_x). */
720void reset_cursor(void)
721{
722 const filestruct *ptr = edittop;
723 size_t x;
724
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000725 /* Yuck. This condition can be true after open_file() when opening
726 * the first file. */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000727 if (edittop == NULL)
728 return;
729
730 current_y = 0;
731
732 while (ptr != current && ptr != editbot && ptr->next != NULL) {
733 ptr = ptr->next;
734 current_y++;
735 }
736
737 x = xplustabs();
738 wmove(edit, current_y, x - get_page_start(x));
739}
Chris Allegretta6df90f52002-07-19 01:08:59 +0000740
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000741/* edit_add() takes care of the job of actually painting a line into
742 * the edit window. Called only from update_line(). Expects a
743 * converted-to-not-have-tabs line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000744void edit_add(const filestruct *fileptr, int yval, int start
745#ifndef NANO_SMALL
746 , int virt_mark_beginx, int virt_cur_x
747#endif
748 )
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000749{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000750#ifdef DEBUG
751 fprintf(stderr, "Painting line %d, current is %d\n", fileptr->lineno,
752 current->lineno);
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000753#endif
754
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000755 /* Just paint the string in any case (we'll add color or reverse on
Chris Allegretta598106e2002-01-19 01:59:37 +0000756 just the text that needs it */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000757 mvwaddnstr(edit, yval, 0, &fileptr->data[start], COLS);
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000758
Chris Allegretta7dd77682001-12-08 19:52:28 +0000759#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +0000760 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000761 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000762
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000763 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
764 int x_start;
765 /* Starting column for mvwaddnstr. Zero-based. */
766 int paintlen;
767 /* number of chars to paint on this line. There are COLS
768 * characters on a whole line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000769 regmatch_t startmatch; /* match position for start_regexp*/
770 regmatch_t endmatch; /* match position for end_regexp*/
771
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000772 if (tmpcolor->bright)
773 wattron(edit, A_BOLD);
774 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
775 /* Two notes about regexec. Return value 0 means there is a
776 * match. Also, rm_eo is the first non-matching character
777 * after the match. */
778
779 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000780 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000781 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000782
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000783 /* We increment k by rm_eo, to move past the end of the
784 last match. Even though two matches may overlap, we
785 want to ignore them, so that we can highlight C-strings
786 correctly. */
787 while (k < start + COLS) {
788 /* Note the fifth parameter to regexec. It says not to
789 * match the beginning-of-line character unless
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000790 * k == 0. If regexec returns nonzero, there are no
791 * more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +0000792 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000793 &startmatch, k == 0 ? 0 : REG_NOTBOL))
794 break;
795 /* Translate the match to the beginning of the line. */
796 startmatch.rm_so += k;
797 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +0000798 if (startmatch.rm_so == startmatch.rm_eo) {
799 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +0000800 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +0000801 } else if (startmatch.rm_so < start + COLS &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000802 startmatch.rm_eo > start) {
803 x_start = startmatch.rm_so - start;
804 if (x_start < 0)
805 x_start = 0;
806 paintlen = startmatch.rm_eo - start - x_start;
807 if (paintlen > COLS - x_start)
808 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000809
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000810 assert(0 <= x_start && 0 < paintlen &&
811 x_start + paintlen <= COLS);
812 mvwaddnstr(edit, yval, x_start,
813 fileptr->data + start + x_start, paintlen);
814 }
815 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +0000816 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000817 } else {
818 /* This is a multi-line regexp. There are two steps.
819 * First, we have to see if the beginning of the line is
820 * colored by a start on an earlier line, and an end on
821 * this line or later.
822 *
823 * We find the first line before fileptr matching the
824 * start. If every match on that line is followed by an
825 * end, then go to step two. Otherwise, find the next line
826 * after start_line matching the end. If that line is not
827 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +0000828
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000829 const filestruct *start_line = fileptr->prev;
830 /* the first line before fileptr matching start*/
831 regoff_t start_col;
832 /* where it starts in that line */
833 const filestruct *end_line;
834 int searched_later_lines = 0;
835 /* Used in step 2. Have we looked for an end on
836 * lines after fileptr? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000837
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000838 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +0000839 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000840 &startmatch, 0)) {
841 /* If there is an end on this line, there is no need
842 * to look for starts on earlier lines. */
Chris Allegrettace452fb2003-02-03 02:56:44 +0000843 if (!regexec(tmpcolor->end, start_line->data, 1,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000844 &endmatch, 0))
845 goto step_two;
846 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000847 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000848 /* No start found, so skip to the next step. */
849 if (start_line == NULL)
850 goto step_two;
851 /* Now start_line is the first line before fileptr
852 * containing a start match. Is there a start on this
853 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000854
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000855 start_col = 0;
856 while (1) {
857 start_col += startmatch.rm_so;
858 startmatch.rm_eo -= startmatch.rm_so;
Chris Allegrettace452fb2003-02-03 02:56:44 +0000859 if (regexec(tmpcolor->end,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000860 start_line->data + start_col + startmatch.rm_eo,
861 1, &endmatch,
862 start_col + startmatch.rm_eo == 0 ? 0 : REG_NOTBOL))
863 /* No end found after this start */
864 break;
865 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +0000866 if (regexec(&tmpcolor->start,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000867 start_line->data + start_col, 1, &startmatch,
868 REG_NOTBOL))
869 /* No later start on this line. */
870 goto step_two;
871 }
872 /* Indeed, there is a start not followed on this line by an
873 * end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000874
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000875 /* We have already checked that there is no end before
876 * fileptr and after the start. Is there an end after
877 * the start at all? We don't paint unterminated starts. */
878 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +0000879 while (end_line != NULL &&
880 regexec(tmpcolor->end, end_line->data, 1, &endmatch, 0))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000881 end_line = end_line->next;
882
883 /* No end found, or it is too early. */
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000884 if (end_line == NULL || end_line->lineno < fileptr->lineno ||
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000885 (end_line == fileptr && endmatch.rm_eo <= start))
886 goto step_two;
887
888 /* Now paint the start of fileptr. */
889 paintlen = end_line != fileptr
890 ? COLS : endmatch.rm_eo - start;
891 if (paintlen > COLS)
892 paintlen = COLS;
893
894 assert(0 < paintlen && paintlen <= COLS);
895 mvwaddnstr(edit, yval, 0, fileptr->data + start, paintlen);
896
897 /* We have already painted the whole line. */
898 if (paintlen == COLS)
899 goto skip_step_two;
900
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000901 step_two: /* Second step, we look for starts on this line. */
902 start_col = 0;
903 while (start_col < start + COLS) {
Chris Allegrettace452fb2003-02-03 02:56:44 +0000904 if (regexec(&tmpcolor->start, fileptr->data + start_col, 1,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000905 &startmatch, start_col == 0 ? 0 : REG_NOTBOL)
906 || start_col + startmatch.rm_so >= start + COLS)
907 /* No more starts on this line. */
908 break;
909 /* Translate the match to be relative to the
910 * beginning of the line. */
911 startmatch.rm_so += start_col;
912 startmatch.rm_eo += start_col;
913
914 x_start = startmatch.rm_so - start;
915 if (x_start < 0) {
916 x_start = 0;
917 startmatch.rm_so = start;
918 }
Chris Allegrettace452fb2003-02-03 02:56:44 +0000919 if (!regexec(tmpcolor->end, fileptr->data + startmatch.rm_eo,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000920 1, &endmatch,
921 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL)) {
922 /* Translate the end match to be relative to the
923 beginning of the line. */
924 endmatch.rm_so += startmatch.rm_eo;
925 endmatch.rm_eo += startmatch.rm_eo;
926 /* There is an end on this line. But does it
927 appear on this page, and is the match more than
928 zero characters long? */
929 if (endmatch.rm_eo > start &&
930 endmatch.rm_eo > startmatch.rm_so) {
931 paintlen = endmatch.rm_eo - start - x_start;
932 if (x_start + paintlen > COLS)
933 paintlen = COLS - x_start;
934
935 assert(0 <= x_start && 0 < paintlen &&
936 x_start + paintlen <= COLS);
937 mvwaddnstr(edit, yval, x_start,
938 fileptr->data + start + x_start, paintlen);
939 }
940 } else if (!searched_later_lines) {
941 searched_later_lines = 1;
942 /* There is no end on this line. But we haven't
943 * yet looked for one on later lines. */
944 end_line = fileptr->next;
Chris Allegrettace452fb2003-02-03 02:56:44 +0000945 while (end_line != NULL && regexec(tmpcolor->end,
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000946 end_line->data, 1, &endmatch, 0))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000947 end_line = end_line->next;
948 if (end_line != NULL) {
949 assert(0 <= x_start && x_start < COLS);
950 mvwaddnstr(edit, yval, x_start,
951 fileptr->data + start + x_start,
952 COLS - x_start);
953 /* We painted to the end of the line, so
954 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000955 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +0000956 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000957 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000958 start_col = startmatch.rm_so + 1;
959 } /* while start_col < start + COLS */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000960 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000961
Chris Allegrettace452fb2003-02-03 02:56:44 +0000962 skip_step_two:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000963 wattroff(edit, A_BOLD);
964 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
965 } /* for tmpcolor in colorstrings */
966 }
Chris Allegretta598106e2002-01-19 01:59:37 +0000967#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000968
Chris Allegretta7dd77682001-12-08 19:52:28 +0000969#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000970 if (ISSET(MARK_ISSET)
971 && (fileptr->lineno <= mark_beginbuf->lineno
972 || fileptr->lineno <= current->lineno)
973 && (fileptr->lineno >= mark_beginbuf->lineno
974 || fileptr->lineno >= current->lineno)) {
975 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000976
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000977 int x_start;
978 /* Starting column for mvwaddnstr. Zero-based. */
979 int paintlen;
980 /* number of chars to paint on this line. There are COLS
981 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +0000982
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000983 if (mark_beginbuf == fileptr && current == fileptr) {
984 x_start = virt_mark_beginx < virt_cur_x ? virt_mark_beginx
985 : virt_cur_x;
986 paintlen = abs(virt_mark_beginx - virt_cur_x);
987 } else {
988 if (mark_beginbuf->lineno < fileptr->lineno ||
989 current->lineno < fileptr->lineno)
990 x_start = 0;
991 else
992 x_start = mark_beginbuf == fileptr ? virt_mark_beginx
993 : virt_cur_x;
994
995 if (mark_beginbuf->lineno > fileptr->lineno ||
996 current->lineno > fileptr->lineno)
997 paintlen = start + COLS;
998 else
999 paintlen = mark_beginbuf == fileptr ? virt_mark_beginx
1000 : virt_cur_x;
1001 }
1002 x_start -= start;
1003 if (x_start < 0) {
1004 paintlen += x_start;
1005 x_start = 0;
1006 }
1007 if (x_start + paintlen > COLS)
1008 paintlen = COLS - x_start;
1009 if (paintlen > 0) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001010 wattron(edit, A_REVERSE);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001011 assert(x_start >= 0 && paintlen > 0 && x_start + paintlen <= COLS);
1012 mvwaddnstr(edit, yval, x_start,
1013 fileptr->data + start + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001014 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001015 }
Chris Allegretta08893e02001-11-29 02:42:27 +00001016 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001017#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001018}
1019
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001020/* Just update one line in the edit buffer. Basically a wrapper for
1021 * edit_add(). If fileptr != current, then index is considered 0.
1022 * The line will be displayed starting with fileptr->data[index].
1023 * Likely args are current_x or 0. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001024void update_line(filestruct *fileptr, int index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001025{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001026 int line;
1027 /* line in the edit window for CURSES calls */
1028#ifndef NANO_SMALL
1029 int virt_cur_x;
1030 int virt_mark_beginx;
1031#endif
1032 char *original;
1033 /* The original string fileptr->data. */
1034 char *converted;
1035 /* fileptr->data converted to have tabs and control characters
1036 * expanded. */
1037 size_t pos;
1038 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001039
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001040 if (fileptr == NULL)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001041 return;
Robert Siemborski53154a72000-06-18 00:11:03 +00001042
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001043 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001044
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001045 /* We assume the line numbers are valid. Is that really true? */
1046 assert(line < 0 || line == check_linenumbers(fileptr));
1047
1048 if (line < 0 || line >= editwinrows)
1049 return;
1050
1051 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001052 mvwaddstr(edit, line, 0, hblank);
1053
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001054 original = fileptr->data;
1055 converted = charalloc(strlenpt(original) + 1);
Chris Allegretta5beed502003-01-05 20:41:21 +00001056
1057 /* Next, convert all the tabs to spaces, so everything else is easy.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001058 * Note the internal speller sends us index == -1. */
1059 index = fileptr == current && index > 0 ? strnlenpt(original, index) : 0;
1060#ifndef NANO_SMALL
1061 virt_cur_x = fileptr == current ? strnlenpt(original, current_x) : current_x;
1062 virt_mark_beginx = fileptr == mark_beginbuf ? strnlenpt(original, mark_beginx) : mark_beginx;
1063#endif
Robert Siemborski53875912000-06-16 04:25:30 +00001064
1065 pos = 0;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001066 for (; *original != '\0'; original++) {
1067 if (*original == '\t')
Robert Siemborski53875912000-06-16 04:25:30 +00001068 do {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001069 converted[pos++] = ' ';
Chris Allegretta6d690a32000-08-03 22:51:21 +00001070 } while (pos % tabsize);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001071 else if (is_cntrl_char(*original)) {
1072 converted[pos++] = '^';
1073 if (*original == 127)
1074 converted[pos++] = '?';
1075 else if (*original == '\n')
1076 /* Treat newlines (ASCII 10's) embedded in a line as encoded
1077 * nulls (ASCII 0's); the line in question should be run
1078 * through unsunder() before reaching here */
1079 converted[pos++] = '@';
1080 else
1081 converted[pos++] = *original + 64;
1082 } else
1083 converted[pos++] = *original;
Robert Siemborski53875912000-06-16 04:25:30 +00001084 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001085 converted[pos] = '\0';
Robert Siemborski53875912000-06-16 04:25:30 +00001086
Chris Allegretta4dc03d52002-05-11 03:04:44 +00001087 /* Now, paint the line */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001088 original = fileptr->data;
1089 fileptr->data = converted;
1090 page_start = get_page_start(index);
1091 edit_add(fileptr, line, page_start
1092#ifndef NANO_SMALL
1093 , virt_mark_beginx, virt_cur_x
1094#endif
1095 );
1096 free(converted);
1097 fileptr->data = original;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001098
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001099 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001100 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001101 if (pos > page_start + COLS)
1102 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001103}
1104
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001105/* This function updates current, based on where current_y is;
1106 * reset_cursor() does the opposite. */
1107void update_cursor(void)
1108{
1109 int i = 0;
1110
1111#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001112 fprintf(stderr, "Moved to (%d, %d) in edit buffer\n", current_y,
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001113 current_x);
1114#endif
1115
1116 current = edittop;
1117 while (i < current_y && current->next != NULL) {
1118 current = current->next;
1119 i++;
1120 }
1121
1122#ifdef DEBUG
Chris Allegretta0e86e602003-01-23 04:27:23 +00001123 fprintf(stderr, "current->data = \"%s\"\n", current->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001124#endif
1125}
1126
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001127void center_cursor(void)
1128{
1129 current_y = editwinrows / 2;
1130 wmove(edit, current_y, current_x);
1131}
1132
Chris Allegretta6df90f52002-07-19 01:08:59 +00001133/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001134void edit_refresh(void)
1135{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001136 /* Neither of these conditions should occur, but they do. edittop is
1137 * NULL when you open an existing file on the command line, and
1138 * ENABLE_COLOR is defined. Yuck. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001139 if (current == NULL)
1140 return;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001141 if (edittop == NULL)
1142 edittop = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001143
Chris Allegretta63d0b482003-01-26 19:47:10 +00001144 if (current->lineno < edittop->lineno ||
1145 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001146 /* Note that edit_update() changes edittop so that
1147 * current->lineno = edittop->lineno + editwinrows / 2. Thus
1148 * when it then calls edit_refresh(), there is no danger of
1149 * getting an infinite loop. */
Chris Allegrettada721be2000-07-31 01:26:42 +00001150 edit_update(current, CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001151 else {
1152 int nlines = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001153
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001154 /* Don't make the cursor jump around the screen whilst updating */
1155 leaveok(edit, TRUE);
1156
1157 editbot = edittop;
1158 while (nlines < editwinrows) {
1159 update_line(editbot, current_x);
1160 nlines++;
1161 if (editbot->next == NULL)
1162 break;
1163 editbot = editbot->next;
1164 }
1165 while (nlines < editwinrows) {
1166 mvwaddstr(edit, nlines, 0, hblank);
1167 nlines++;
1168 }
1169 /* What the hell are we expecting to update the screen if this
Chris Allegretta7662c862003-01-13 01:35:15 +00001170 isn't here? Luck? */
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001171 wrefresh(edit);
1172 leaveok(edit, FALSE);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001173 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001174}
1175
Chris Allegretta7662c862003-01-13 01:35:15 +00001176/* Same as above, but touch the window first, so everything is
1177 * redrawn. */
Chris Allegrettaf1d33d32000-08-19 03:53:39 +00001178void edit_refresh_clearok(void)
1179{
1180 clearok(edit, TRUE);
1181 edit_refresh();
1182 clearok(edit, FALSE);
1183}
1184
1185/*
Chris Allegretta88520c92001-05-05 17:45:54 +00001186 * Nice generic routine to update the edit buffer, given a pointer to the
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001187 * file struct =)
1188 */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001189void edit_update(filestruct *fileptr, topmidbotnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001190{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001191 if (fileptr == NULL)
1192 return;
1193
Chris Allegretta6df90f52002-07-19 01:08:59 +00001194 if (location != TOP) {
1195 int goal = location == NONE ? current_y - 1 : editwinrows / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001196
Chris Allegretta6df90f52002-07-19 01:08:59 +00001197 for (; goal >= 0 && fileptr->prev != NULL; goal--)
1198 fileptr = fileptr->prev;
1199 }
1200 edittop = fileptr;
Robert Siemborski29e9a762000-07-05 03:16:04 +00001201 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001202
1203 edit_refresh();
1204}
1205
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001206/*
1207 * Ask a question on the statusbar. Answer will be stored in answer
1208 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
Chris Allegretta88520c92001-05-05 17:45:54 +00001209 * otherwise, the valid shortcut key caught. Def is any editable text we
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001210 * want to put up by default.
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00001211 *
1212 * New arg tabs tells whether or not to allow tab completion.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001213 */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001214int statusq(int tabs, const shortcut *s, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00001215#ifndef NANO_SMALL
1216 historyheadtype *which_history,
1217#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001218 const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001219{
1220 va_list ap;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001221 char *foo = charalloc(COLS - 3);
Chris Allegretta9caa1932002-02-15 20:08:05 +00001222 int ret;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001223#ifndef DISABLE_TABCOMP
Chris Allegrettaa16e4e92002-01-05 18:59:54 +00001224 int list = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001225#endif
1226
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001227 bottombars(s);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001228
1229 va_start(ap, msg);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001230 vsnprintf(foo, COLS - 4, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001231 va_end(ap);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001232 foo[COLS - 4] = '\0';
Chris Allegretta8ce24132001-04-30 11:28:46 +00001233
Chris Allegretta5beed502003-01-05 20:41:21 +00001234 ret = nanogetstr(tabs, foo, def,
1235#ifndef NANO_SMALL
1236 which_history,
Chris Allegretta2084acc2001-11-29 03:43:08 +00001237#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00001238 s
1239#ifndef DISABLE_TABCOMP
1240 , &list
1241#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00001242 );
Chris Allegretta6df90f52002-07-19 01:08:59 +00001243 free(foo);
Chris Allegretta65f075d2003-02-13 03:03:49 +00001244 resetstatuspos = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001245
1246 switch (ret) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001247 case NANO_FIRSTLINE_KEY:
1248 do_first_line();
Chris Allegretta65f075d2003-02-13 03:03:49 +00001249 resetstatuspos = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001250 break;
1251 case NANO_LASTLINE_KEY:
1252 do_last_line();
Chris Allegretta65f075d2003-02-13 03:03:49 +00001253 resetstatuspos = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001254 break;
1255 case NANO_CANCEL_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001256 ret = -1;
Chris Allegretta65f075d2003-02-13 03:03:49 +00001257 resetstatuspos = 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001258 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001259 }
Chris Allegrettaa90d0cf2003-02-10 02:55:03 +00001260 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001261
1262#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001263 fprintf(stderr, "I got \"%s\"\n", answer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001264#endif
1265
Chris Allegretta6df90f52002-07-19 01:08:59 +00001266#ifndef DISABLE_TABCOMP
1267 /* if we've done tab completion, there might be a list of
1268 filename matches on the edit window at this point; make sure
1269 they're cleared off */
1270 if (list)
1271 edit_refresh();
1272#endif
1273
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001274 return ret;
1275}
1276
1277/*
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001278 * Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001279 * for N, 2 for All (if all is nonzero when passed in) and -1 for abort
1280 * (^C).
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001281 */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001282int do_yesno(int all, int leavecursor, const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001283{
1284 va_list ap;
Chris Allegrettadb28e962003-01-28 01:23:40 +00001285 char *foo;
1286 int ok = -2;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001287 const char *yesstr; /* String of yes characters accepted */
1288 const char *nostr; /* Same for no */
1289 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00001290
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001291 /* Yes, no and all are strings of any length. Each string consists of
Chris Allegretta598106e2002-01-19 01:59:37 +00001292 all characters accepted as a valid character for that value.
1293 The first value will be the one displayed in the shortcuts. */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001294 yesstr = _("Yy");
1295 nostr = _("Nn");
1296 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001297
Jordi Mallach0b0fc492000-06-23 01:00:13 +00001298 /* Remove gettext call for keybindings until we clear the thing up */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001299 if (!ISSET(NO_HELP)) {
Chris Allegretta6232d662002-05-12 19:52:15 +00001300 char shortstr[3]; /* Temp string for Y, N, A */
1301
Chris Allegrettadb28e962003-01-28 01:23:40 +00001302 /* Write the bottom of the screen */
1303 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001304
Chris Allegretta6232d662002-05-12 19:52:15 +00001305 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00001306 wmove(bottomwin, 1, 0);
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001307 onekey(shortstr, _("Yes"), 16);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001308
1309 if (all) {
Chris Allegrettadb28e962003-01-28 01:23:40 +00001310 wmove(bottomwin, 1, 16);
Chris Allegretta6232d662002-05-12 19:52:15 +00001311 shortstr[1] = allstr[0];
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001312 onekey(shortstr, _("All"), 16);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001313 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001314
Chris Allegrettadb28e962003-01-28 01:23:40 +00001315 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00001316 shortstr[1] = nostr[0];
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001317 onekey(shortstr, _("No"), 16);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001318
Chris Allegrettadb28e962003-01-28 01:23:40 +00001319 wmove(bottomwin, 2, 16);
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001320 onekey("^C", _("Cancel"), 16);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001321 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00001322
1323 foo = charalloc(COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001324 va_start(ap, msg);
Chris Allegrettadb28e962003-01-28 01:23:40 +00001325 vsnprintf(foo, COLS, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001326 va_end(ap);
Chris Allegrettadb28e962003-01-28 01:23:40 +00001327 foo[COLS - 1] = '\0';
Chris Allegretta8ce24132001-04-30 11:28:46 +00001328
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001329 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001330
1331 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001332 mvwaddstr(bottomwin, 0, 0, foo);
Chris Allegrettadb28e962003-01-28 01:23:40 +00001333 free(foo);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001334
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001335 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001336
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001337 wrefresh(bottomwin);
1338
Chris Allegrettadb28e962003-01-28 01:23:40 +00001339 do {
1340 int kbinput = wgetch(edit);
Chris Allegrettab2cd2482003-02-12 23:18:19 +00001341#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegrettadb28e962003-01-28 01:23:40 +00001342 MEVENT mevent;
Chris Allegretta235ab192001-04-12 13:24:40 +00001343#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001344
Chris Allegrettadb28e962003-01-28 01:23:40 +00001345 if (kbinput == NANO_CONTROL_C)
1346 ok = -1;
Chris Allegrettab2cd2482003-02-12 23:18:19 +00001347#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegrettadb28e962003-01-28 01:23:40 +00001348 /* Look ma! We get to duplicate lots of code from do_mouse!! */
1349 else if (kbinput == KEY_MOUSE && getmouse(&mevent) != ERR &&
1350 wenclose(bottomwin, mevent.y, mevent.x) &&
1351 !ISSET(NO_HELP) && mevent.x < 32 &&
1352 mevent.y >= editwinrows + 3) {
1353 int x = mevent.x /= 16;
1354 /* Did we click in the first column of shortcuts, or the
1355 second? */
1356 int y = mevent.y - editwinrows - 3;
1357 /* Did we click in the first row of shortcuts? */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001358
Chris Allegrettadb28e962003-01-28 01:23:40 +00001359 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
1360 /* x = 0 means they clicked Yes or No.
1361 y = 0 means Yes or All. */
1362 ok = -2 * x * y + x - y + 1;
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001363
Chris Allegrettadb28e962003-01-28 01:23:40 +00001364 if (ok == 2 && !all)
1365 ok = -2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001366 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00001367#endif
1368 /* Look for the kbinput in the yes, no and (optionally) all str */
1369 else if (strchr(yesstr, kbinput) != NULL)
1370 ok = 1;
1371 else if (strchr(nostr, kbinput) != NULL)
1372 ok = 0;
1373 else if (all && strchr(allstr, kbinput) != NULL)
1374 ok = 2;
1375 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001376
Chris Allegrettadb28e962003-01-28 01:23:40 +00001377 /* Then blank the statusbar. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001378 blank_statusbar_refresh();
1379
Chris Allegrettadb28e962003-01-28 01:23:40 +00001380 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001381}
1382
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001383int total_refresh(void)
1384{
1385 clearok(edit, TRUE);
1386 clearok(topwin, TRUE);
1387 clearok(bottomwin, TRUE);
1388 wnoutrefresh(edit);
1389 wnoutrefresh(topwin);
1390 wnoutrefresh(bottomwin);
1391 doupdate();
1392 clearok(edit, FALSE);
1393 clearok(topwin, FALSE);
1394 clearok(bottomwin, FALSE);
1395 edit_refresh();
1396 titlebar(NULL);
1397 return 1;
1398}
1399
1400void display_main_list(void)
1401{
1402 bottombars(main_list);
1403}
1404
Chris Allegretta6df90f52002-07-19 01:08:59 +00001405void statusbar(const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001406{
1407 va_list ap;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001408 char *foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001409 int start_x = 0;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001410 size_t foo_len;
1411
Chris Allegrettaa0d89972003-02-03 03:32:08 +00001412 va_start(ap, msg);
1413
1414 /* Curses mode is turned off. If we use wmove() now, it will muck up
1415 the terminal settings. So we just use vfprintf(). */
1416 if (curses_ended) {
1417 vfprintf(stderr, msg, ap);
1418 va_end(ap);
1419 return;
1420 }
1421
Chris Allegretta6df90f52002-07-19 01:08:59 +00001422 assert(COLS >= 4);
1423 foo = charalloc(COLS - 3);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001424
Chris Allegretta6df90f52002-07-19 01:08:59 +00001425 vsnprintf(foo, COLS - 3, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001426 va_end(ap);
1427
Chris Allegretta6df90f52002-07-19 01:08:59 +00001428 foo[COLS - 4] = '\0';
1429 foo_len = strlen(foo);
1430 start_x = (COLS - foo_len - 4) / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001431
1432 /* Blank out line */
1433 blank_statusbar();
1434
1435 wmove(bottomwin, 0, start_x);
1436
1437 wattron(bottomwin, A_REVERSE);
1438
1439 waddstr(bottomwin, "[ ");
1440 waddstr(bottomwin, foo);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001441 free(foo);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001442 waddstr(bottomwin, " ]");
Chris Allegretta8ce24132001-04-30 11:28:46 +00001443
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001444 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001445
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001446 wrefresh(bottomwin);
1447
Chris Allegrettad26ab912003-01-28 01:16:47 +00001448 SET(DISABLE_CURPOS);
1449 statblank = 26;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001450}
1451
Chris Allegrettad26ab912003-01-28 01:16:47 +00001452/*
1453 * If constant is false, the user typed ^C so we unconditionally display
1454 * the cursor position. Otherwise, we display it only if the character
1455 * position changed, and DISABLE_CURPOS is not set.
1456 *
1457 * If constant and DISABLE_CURPOS is set, we unset it and update old_i and
1458 * old_totsize. That way, we leave the current statusbar alone, but next
1459 * time we will display. */
Chris Allegretta2084acc2001-11-29 03:43:08 +00001460int do_cursorpos(int constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001461{
Chris Allegrettad26ab912003-01-28 01:16:47 +00001462 const filestruct *fileptr;
1463 unsigned long i = 0;
1464 static unsigned long old_i = 0;
1465 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001466
Chris Allegrettad26ab912003-01-28 01:16:47 +00001467 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00001468
1469 if (old_totsize == -1)
1470 old_totsize = totsize;
1471
Chris Allegrettad26ab912003-01-28 01:16:47 +00001472 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
1473 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001474 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00001475 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001476 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00001477
Chris Allegrettad26ab912003-01-28 01:16:47 +00001478 if (constant && ISSET(DISABLE_CURPOS)) {
1479 UNSET(DISABLE_CURPOS);
1480 old_i = i;
1481 old_totsize = totsize;
1482 return 0;
1483 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00001484
Chris Allegrettad26ab912003-01-28 01:16:47 +00001485 /* if constant is false, display the position on the statusbar
Chris Allegretta2084acc2001-11-29 03:43:08 +00001486 unconditionally; otherwise, only display the position when the
1487 character values have changed */
Chris Allegrettad26ab912003-01-28 01:16:47 +00001488 if (!constant || old_i != i || old_totsize != totsize) {
1489 unsigned long xpt = xplustabs() + 1;
1490 unsigned long cur_len = strlenpt(current->data) + 1;
1491 int linepct = 100 * current->lineno / totlines;
1492 int colpct = 100 * xpt / cur_len;
1493 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
1494
1495 statusbar(
1496 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
1497 current->lineno, totlines, linepct,
1498 xpt, cur_len, colpct,
1499 i, totsize, bytepct);
1500 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00001501 }
1502
1503 old_i = i;
1504 old_totsize = totsize;
1505
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001506 reset_cursor();
Chris Allegrettad26ab912003-01-28 01:16:47 +00001507 return 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001508}
1509
Chris Allegretta2084acc2001-11-29 03:43:08 +00001510int do_cursorpos_void(void)
1511{
1512 return do_cursorpos(0);
1513}
1514
Chris Allegretta4640fe32003-02-10 03:10:03 +00001515/* Calculate the next line of help_text, starting at ptr. */
1516int line_len(const char *ptr)
1517{
1518 int j = 0;
1519
1520 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
1521 ptr++;
1522 j++;
1523 }
1524 if (j == COLS - 5) {
1525 /* Don't wrap at the first of two spaces following a period. */
1526 if (*ptr == ' ' && *(ptr + 1) == ' ')
1527 j++;
1528 /* Don't print half a word if we've run out of space */
1529 while (*ptr != ' ' && j > 0) {
1530 ptr--;
1531 j--;
1532 }
1533 /* Word longer than COLS - 5 chars just gets broken */
1534 if (j == 0)
1535 j = COLS - 5;
1536 }
1537 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
1538 return j;
1539}
1540
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001541/* Our shortcut-list-compliant help function, which is
1542 * better than nothing, and dynamic! */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001543int do_help(void)
1544{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001545#ifndef DISABLE_HELP
Chris Allegretta653d6142003-08-04 02:12:03 +00001546 int i, page = 0, kbinput = 0, no_more = 0, kp;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001547 int no_help_flag = 0;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001548 const shortcut *oldshortcut;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001549
1550 blank_edit();
1551 curs_set(0);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001552 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001553 blank_statusbar();
1554
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001555 /* set help_text as the string to display */
Chris Allegrettab3655b42001-10-22 03:15:31 +00001556 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001557 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001558
1559 oldshortcut = currshortcut;
Chris Allegrettab3655b42001-10-22 03:15:31 +00001560
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001561 currshortcut = help_list;
Chris Allegretta6fe61492001-05-21 12:56:25 +00001562
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001563 kp = keypad_on(edit, 1);
1564
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001565 if (ISSET(NO_HELP)) {
1566
Chris Allegretta88520c92001-05-05 17:45:54 +00001567 /* Well, if we're going to do this, we should at least
Chris Allegretta70444892001-01-07 23:02:02 +00001568 do it the right way */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001569 no_help_flag = 1;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001570 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00001571 window_init();
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001572 bottombars(help_list);
Chris Allegretta70444892001-01-07 23:02:02 +00001573
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001574 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001575 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001576
1577 do {
Chris Allegrettaf717f982003-02-13 22:25:01 +00001578 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001579
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001580 switch (kbinput) {
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001581#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegretta598106e2002-01-19 01:59:37 +00001582 case KEY_MOUSE:
1583 do_mouse();
1584 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001585#endif
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001586 case 27:
1587 kbinput = wgetch(edit);
1588 switch(kbinput) {
1589 case '[':
1590 kbinput = wgetch(edit);
1591 switch(kbinput) {
1592 case '5': /* Alt-[-5 = Page Up */
1593 wgetch(edit);
1594 goto do_pageupkey;
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001595 case 'V': /* Alt-[-V = Page Up in Hurd Console */
1596 case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
1597 goto do_pageupkey;
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001598 case '6': /* Alt-[-6 = Page Down */
1599 wgetch(edit);
1600 goto do_pagedownkey;
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001601 case 'U': /* Alt-[-U = Page Down in Hurd Console */
1602 case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
1603 goto do_pagedownkey;
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001604 }
1605 break;
1606 }
1607 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001608 case NANO_NEXTPAGE_KEY:
1609 case NANO_NEXTPAGE_FKEY:
1610 case KEY_NPAGE:
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001611 do_pagedownkey:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001612 if (!no_more) {
1613 blank_edit();
1614 page++;
1615 }
1616 break;
1617 case NANO_PREVPAGE_KEY:
1618 case NANO_PREVPAGE_FKEY:
1619 case KEY_PPAGE:
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001620 do_pageupkey:
Chris Allegretta4640fe32003-02-10 03:10:03 +00001621 if (page > 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001622 no_more = 0;
1623 blank_edit();
1624 page--;
1625 }
1626 break;
1627 }
1628
Chris Allegretta88520c92001-05-05 17:45:54 +00001629 /* Calculate where in the text we should be, based on the page */
Chris Allegretta4640fe32003-02-10 03:10:03 +00001630 for (i = 1; i < page * (editwinrows - 1); i++) {
1631 ptr += line_len(ptr);
1632 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001633 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001634 }
1635
Chris Allegretta4640fe32003-02-10 03:10:03 +00001636 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
1637 int j = line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001638
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001639 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00001640 ptr += j;
1641 if (*ptr == '\n')
1642 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001643 }
Chris Allegretta4640fe32003-02-10 03:10:03 +00001644
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001645 if (*ptr == '\0') {
1646 no_more = 1;
1647 continue;
1648 }
Chris Allegretta598106e2002-01-19 01:59:37 +00001649 } while ((kbinput = wgetch(edit)) != NANO_EXIT_KEY &&
1650 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00001651
Chris Allegrettab3655b42001-10-22 03:15:31 +00001652 currshortcut = oldshortcut;
Chris Allegrettab3655b42001-10-22 03:15:31 +00001653
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001654 if (no_help_flag) {
Chris Allegretta70444892001-01-07 23:02:02 +00001655 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001656 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001657 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00001658 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00001659 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001660 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001661
1662 curs_set(1);
1663 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001664 kp = keypad_on(edit, kp);
1665
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001666 /* The help_init() at the beginning allocated help_text, which has
1667 now been written to screen. */
1668 free(help_text);
1669 help_text = NULL;
1670
Chris Allegretta6df90f52002-07-19 01:08:59 +00001671#elif defined(DISABLE_HELP)
1672 nano_disabled_msg();
1673#endif
1674
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001675 return 1;
1676}
1677
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001678int keypad_on(WINDOW *win, int newval)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001679{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001680/* This is taken right from aumix. Don't sue me. */
1681#ifdef HAVE_USEKEYPAD
1682 int old = win->_use_keypad;
1683 keypad(win, newval);
1684 return old;
1685#else
1686 keypad(win, newval);
1687 return 1;
1688#endif /* HAVE_USEKEYPAD */
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001689}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001690
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001691/* Highlight the current word being replaced or spell checked. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001692void do_replace_highlight(int highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00001693{
1694 char *highlight_word = NULL;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001695 int x, y, word_len;
Chris Allegrettafb62f732000-12-05 11:36:41 +00001696
Chris Allegretta598106e2002-01-19 01:59:37 +00001697 highlight_word =
1698 mallocstrcpy(highlight_word, &current->data[current_x]);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001699
1700#ifdef HAVE_REGEX_H
1701 if (ISSET(USE_REGEXP))
1702 /* if we're using regexps, the highlight is the length of the
1703 search result, not the length of the regexp string */
1704 word_len = regmatches[0].rm_eo - regmatches[0].rm_so;
1705 else
1706#endif
1707 word_len = strlen(word);
1708
1709 highlight_word[word_len] = '\0';
Chris Allegrettafb62f732000-12-05 11:36:41 +00001710
Chris Allegretta88520c92001-05-05 17:45:54 +00001711 /* adjust output when word extends beyond screen */
Chris Allegrettafb62f732000-12-05 11:36:41 +00001712
1713 x = xplustabs();
Chris Allegretta6df90f52002-07-19 01:08:59 +00001714 y = get_page_start(x) + COLS;
Chris Allegrettafb62f732000-12-05 11:36:41 +00001715
Chris Allegretta6df90f52002-07-19 01:08:59 +00001716 if ((COLS - (y - x) + word_len) > COLS) {
Chris Allegrettafb62f732000-12-05 11:36:41 +00001717 highlight_word[y - x - 1] = '$';
1718 highlight_word[y - x] = '\0';
1719 }
1720
1721 /* OK display the output */
1722
1723 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00001724
Chris Allegrettafb62f732000-12-05 11:36:41 +00001725 if (highlight_flag)
1726 wattron(edit, A_REVERSE);
1727
1728 waddstr(edit, highlight_word);
1729
1730 if (highlight_flag)
1731 wattroff(edit, A_REVERSE);
1732
1733 free(highlight_word);
1734}
1735
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001736/* Fix editbot, based on the assumption that edittop is correct. */
1737void fix_editbot(void)
1738{
1739 int i;
1740
1741 editbot = edittop;
1742 for (i = 0; i < editwinrows && editbot->next != NULL; i++)
1743 editbot = editbot->next;
1744}
1745
1746#ifdef DEBUG
1747/* Dump the current file structure to stderr */
1748void dump_buffer(const filestruct *inptr) {
1749 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00001750 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001751 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00001752 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001753 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00001754 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001755
1756 while (inptr != NULL) {
1757 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
1758 inptr = inptr->next;
1759 }
1760}
1761#endif /* DEBUG */
1762
1763#ifdef DEBUG
1764void dump_buffer_reverse(void) {
1765 const filestruct *fileptr = filebot;
1766
1767 while (fileptr != NULL) {
1768 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
1769 fileptr = fileptr->prev;
1770 }
1771}
1772#endif /* DEBUG */
1773
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001774#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00001775#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001776#define XLCREDIT_LEN 8
1777
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001778void do_credits(void)
1779{
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001780 int i, j = 0, k, place = 0, start_x;
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001781
Chris Allegrettaf717f982003-02-13 22:25:01 +00001782 const char *what;
1783 const char *xlcredits[XLCREDIT_LEN];
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001784
Chris Allegrettaf717f982003-02-13 22:25:01 +00001785 const char *credits[CREDIT_LEN] = {
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001786 "0", /* "The nano text editor" */
1787 "1", /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001788 VERSION,
1789 "",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001790 "2", /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001791 "Chris Allegretta",
1792 "Jordi Mallach",
1793 "Adam Rogoyski",
1794 "Rob Siemborski",
1795 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001796 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00001797 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00001798 "Ken Tyler",
1799 "Sven Guckes",
1800 "Florian König",
1801 "Pauli Virtanen",
1802 "Daniele Medri",
1803 "Clement Laforet",
1804 "Tedi Heriyanto",
1805 "Bill Soudan",
1806 "Christian Weisgerber",
1807 "Erik Andersen",
1808 "Big Gaute",
1809 "Joshua Jensen",
1810 "Ryan Krebs",
1811 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00001812 "",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001813 "3", /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001814 "Plattsburgh State University",
1815 "Benet Laboratories",
1816 "Amy Allegretta",
1817 "Linda Young",
1818 "Jeremy Robichaud",
1819 "Richard Kolb II",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001820 "4", /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001821 "Linus Torvalds",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001822 "5", /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00001823 "Thomas Dickey",
1824 "Pavel Curtis",
1825 "Zeyd Ben-Halim",
1826 "Eric S. Raymond",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001827 "6", /* "and anyone else we forgot..." */
1828 "7", /* "Thank you for using nano!\n" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001829 "", "", "", "",
1830 "(c) 1999-2002 Chris Allegretta",
1831 "", "", "", "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00001832 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001833 };
1834
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001835 xlcredits[0] = _("The nano text editor");
1836 xlcredits[1] = _("version ");
1837 xlcredits[2] = _("Brought to you by:");
1838 xlcredits[3] = _("Special thanks to:");
1839 xlcredits[4] = _("The Free Software Foundation");
1840 xlcredits[5] = _("For ncurses:");
1841 xlcredits[6] = _("and anyone else we forgot...");
1842 xlcredits[7] = _("Thank you for using nano!\n");
1843
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001844 curs_set(0);
1845 nodelay(edit, TRUE);
1846 blank_bottombars();
1847 mvwaddstr(topwin, 0, 0, hblank);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001848 blank_edit();
1849 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001850 wrefresh(bottomwin);
1851 wrefresh(topwin);
1852
1853 while (wgetch(edit) == ERR) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001854 for (k = 0; k <= 1; k++) {
1855 blank_edit();
Chris Allegretta598106e2002-01-19 01:59:37 +00001856 for (i = editwinrows / 2 - 1; i >= (editwinrows / 2 - 1 - j);
1857 i--) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001858 mvwaddstr(edit, i * 2 - k, 0, hblank);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001859
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001860 if (place - (editwinrows / 2 - 1 - i) < CREDIT_LEN) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001861 what = credits[place - (editwinrows / 2 - 1 - i)];
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001862
1863 /* God I've missed hacking. If what is exactly
1864 1 char long, it's a sentinel for a translated
1865 string, so use that instead. This means no
1866 thanking people with 1 character long names ;-) */
1867 if (strlen(what) == 1)
1868 what = xlcredits[atoi(what)];
1869 } else
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001870 what = "";
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001871
Chris Allegretta17dcb722001-01-20 21:40:07 +00001872 start_x = COLS / 2 - strlen(what) / 2 - 1;
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001873 mvwaddstr(edit, i * 2 - k, start_x, what);
1874 }
1875 usleep(700000);
1876 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001877 }
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001878 if (j < editwinrows / 2 - 1)
1879 j++;
1880
1881 place++;
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001882
1883 if (place >= CREDIT_LEN + editwinrows / 2)
1884 break;
1885 }
1886
1887 nodelay(edit, FALSE);
1888 curs_set(1);
1889 display_main_list();
1890 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00001891}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001892#endif