blob: 221fb1329244d9fe14a870a311a55c47a4ec1945 [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
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 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! */
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
Chris Allegretta47fcfe52003-01-26 21:01:16 +0000197 , int resetpos)
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;
Chris Allegretta8031f832003-01-09 05:29:58 +0000213 int last_kbinput = 0, ret2cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +0000214#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +0000215 xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +0000216
217 /* Only put x at the end of the string if it's uninitialized or if
218 it would be past the end of the string as it is. Otherwise,
219 leave it alone. This is so the cursor position stays at the same
220 place if a prompt-changing toggle is pressed. */
Chris Allegretta47fcfe52003-01-26 21:01:16 +0000221 if (x == -1 || x > xend || resetpos)
Chris Allegretta09fc4302003-01-16 22:16:38 +0000222 x = xend;
223
Chris Allegretta6df90f52002-07-19 01:08:59 +0000224 answer = (char *)nrealloc(answer, xend + 1);
225 if (xend > 0)
226 strcpy(answer, def);
227 else
228 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000229
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000230#if !defined(DISABLE_HELP) || (!defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION))
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000231 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +0000232#endif
233
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000234 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +0000235
Chris Allegretta6df90f52002-07-19 01:08:59 +0000236 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000237
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000238 /* Make sure any editor screen updates are displayed before getting
239 input */
Chris Allegretta022b96f2000-11-14 17:47:58 +0000240 wrefresh(edit);
241
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000242 while ((kbinput = wgetch(bottomwin)) != 13) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000243 for (t = s; t != NULL; t = t->next) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000244#ifdef DEBUG
245 fprintf(stderr, _("Aha! \'%c\' (%d)\n"), kbinput, kbinput);
246#endif
247
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000248 if (kbinput == t->val && kbinput < 32) {
Chris Allegretta5bf51d32000-11-16 06:01:10 +0000249
Chris Allegrettab3655b42001-10-22 03:15:31 +0000250#ifndef DISABLE_HELP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000251 /* Have to do this here, it would be too late to do it
252 in statusq() */
Chris Allegretta598106e2002-01-19 01:59:37 +0000253 if (kbinput == NANO_HELP_KEY || kbinput == NANO_HELP_FKEY) {
Chris Allegrettab3655b42001-10-22 03:15:31 +0000254 do_help();
255 break;
256 }
257#endif
Chris Allegretta5af58892003-01-17 21:07:38 +0000258
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000259 return t->val;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000260 }
261 }
Chris Allegretta6df90f52002-07-19 01:08:59 +0000262 assert(0 <= x && x <= xend && xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000263
Chris Allegretta04d848e2000-11-05 17:54:41 +0000264 if (kbinput != '\t')
265 tabbed = 0;
266
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000267 switch (kbinput) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000268
Chris Allegretta598106e2002-01-19 01:59:37 +0000269 /* Stuff we want to equate with <enter>, ASCII 13 */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000270 case 343:
Chris Allegrettaf9b6c9b2000-10-18 19:35:59 +0000271 ungetch(13); /* Enter on iris-ansi $TERM, sometimes */
272 break;
Chris Allegretta598106e2002-01-19 01:59:37 +0000273 /* Stuff we want to ignore */
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000274#ifdef PDCURSES
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000275 case 541:
276 case 542:
Chris Allegretta598106e2002-01-19 01:59:37 +0000277 case 543: /* Right ctrl again */
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000278 case 544:
Chris Allegretta598106e2002-01-19 01:59:37 +0000279 case 545: /* Right alt again */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000280 break;
Chris Allegretta5b1faac2000-11-16 19:55:30 +0000281#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000282#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000283 case KEY_MOUSE:
284 do_mouse();
285 break;
286#endif
Chris Allegretta658399a2001-06-14 02:54:22 +0000287 case NANO_HOME_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000288 case KEY_HOME:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000289 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000290 break;
Chris Allegretta658399a2001-06-14 02:54:22 +0000291 case NANO_END_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000292 case KEY_END:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000293 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000294 break;
295 case KEY_RIGHT:
Chris Allegretta35dac582001-03-21 15:07:20 +0000296 case NANO_FORWARD_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000297 if (x < xend)
298 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000299 break;
300 case NANO_CONTROL_D:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000301 if (x < xend) {
302 memmove(answer + x, answer + x + 1, xend - x);
303 xend--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000304 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000305 break;
306 case NANO_CONTROL_K:
307 case NANO_CONTROL_U:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000308 null_at(&answer, 0);
309 xend = 0;
310 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000311 break;
312 case KEY_BACKSPACE:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000313 case 127:
314 case NANO_CONTROL_H:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000315 if (x > 0) {
316 memmove(answer + x - 1, answer + x, xend - x + 1);
Chris Allegretta04d848e2000-11-05 17:54:41 +0000317 x--;
Chris Allegretta6df90f52002-07-19 01:08:59 +0000318 xend--;
319 }
Chris Allegretta04d848e2000-11-05 17:54:41 +0000320 break;
321 case NANO_CONTROL_I:
Chris Allegretta5beed502003-01-05 20:41:21 +0000322#ifndef NANO_SMALL
323 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +0000324 if (history_list != NULL) {
325 if (!complete || last_kbinput != NANO_CONTROL_I) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000326 history_list->current = (historytype *)history_list;
327 history_list->len = strlen(answer);
328 }
Chris Allegretta6df90f52002-07-19 01:08:59 +0000329
Chris Allegretta7662c862003-01-13 01:35:15 +0000330 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000331 complete = get_history_completion(history_list, answer);
332 xend = strlen(complete);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000333 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +0000334 answer = mallocstrcpy(answer, complete);
335 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +0000336 }
Chris Allegretta5beed502003-01-05 20:41:21 +0000337#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +0000338 else
339#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +0000340#endif
Chris Allegretta5beed502003-01-05 20:41:21 +0000341#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +0000342 if (allowtabs) {
343 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +0000344
Chris Allegretta327abda2003-01-17 05:04:17 +0000345 answer = input_tab(answer, x, &tabbed, &shift, list);
346 xend = strlen(answer);
347 x += shift;
348 if (x > xend)
349 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +0000350 }
351#endif
352 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000353 case KEY_LEFT:
Chris Allegretta35dac582001-03-21 15:07:20 +0000354 case NANO_BACK_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000355 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000356 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000357 break;
358 case KEY_UP:
Chris Allegretta7662c862003-01-13 01:35:15 +0000359 case NANO_UP_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +0000360#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +0000361 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +0000362
Chris Allegretta7662c862003-01-13 01:35:15 +0000363 /* If there's no previous temp holder, or if we already
364 arrowed back down to it and (possibly edited it),
365 update the holder */
Chris Allegretta8031f832003-01-09 05:29:58 +0000366 if (currentbuf == NULL || (ret2cb == 1 && strcmp(currentbuf, answer))) {
367 currentbuf = mallocstrcpy(currentbuf, answer);
368 ret2cb = 0;
369 }
370
Chris Allegretta5beed502003-01-05 20:41:21 +0000371 /* get older search from the history list */
Chris Allegretta7662c862003-01-13 01:35:15 +0000372 if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000373 answer = mallocstrcpy(answer, history);
374 xend = strlen(history);
375 } else {
376 answer = mallocstrcpy(answer, "");
377 xend = 0;
378 }
379 x = xend;
380 }
Chris Allegretta5beed502003-01-05 20:41:21 +0000381#endif
Chris Allegretta54abd942003-01-09 23:43:12 +0000382 break;
Chris Allegretta5beed502003-01-05 20:41:21 +0000383 case KEY_DOWN:
Chris Allegretta7662c862003-01-13 01:35:15 +0000384 case NANO_DOWN_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +0000385#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +0000386 if (history_list != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000387 /* get newer search from the history list */
Chris Allegretta7662c862003-01-13 01:35:15 +0000388 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +0000389 answer = mallocstrcpy(answer, history);
390 xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +0000391
Chris Allegretta09fc4302003-01-16 22:16:38 +0000392 /* else if we ran out of history, regurgitate the temporary
393 buffer and blow away currentbuf */
Chris Allegretta8031f832003-01-09 05:29:58 +0000394 } else if (currentbuf != NULL) {
395 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +0000396 free(currentbuf);
397 currentbuf = NULL;
398 xend = strlen(answer);
Chris Allegretta8031f832003-01-09 05:29:58 +0000399 ret2cb = 1;
Chris Allegretta5beed502003-01-05 20:41:21 +0000400 } else {
401 answer = mallocstrcpy(answer, "");
402 xend = 0;
403 }
404 x = xend;
405 }
406#endif
407 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000408 case KEY_DC:
409 goto do_deletekey;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000410 case 27:
411 switch (kbinput = wgetch(edit)) {
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000412 case 'O':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000413 switch (kbinput = wgetch(edit)) {
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000414 case 'F':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000415 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000416 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000417 case 'H':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000418 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000419 break;
420 }
421 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000422 case '[':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000423 switch (kbinput = wgetch(edit)) {
424 case 'C':
425 if (x < xend)
426 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000427 break;
428 case 'D':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000429 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000430 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000431 break;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000432 case '1':
433 case '7':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000434 x = 0;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000435 goto skip_tilde;
436 case '3':
437 do_deletekey:
Chris Allegretta6df90f52002-07-19 01:08:59 +0000438 if (x < xend) {
439 memmove(answer + x, answer + x + 1, xend - x);
440 xend--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000441 }
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000442 goto skip_tilde;
443 case '4':
444 case '8':
Chris Allegretta6df90f52002-07-19 01:08:59 +0000445 x = xend;
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000446 skip_tilde:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000447 nodelay(edit, TRUE);
448 kbinput = wgetch(edit);
Chris Allegrettace78c1e2001-09-23 01:18:03 +0000449 if (kbinput == '~' || kbinput == ERR)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000450 kbinput = -1;
451 nodelay(edit, FALSE);
452 break;
453 }
Chris Allegretta6df90f52002-07-19 01:08:59 +0000454 break;
Chris Allegretta658399a2001-06-14 02:54:22 +0000455 default:
456
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000457 for (t = s; t != NULL; t = t->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +0000458#ifdef DEBUG
Chris Allegretta598106e2002-01-19 01:59:37 +0000459 fprintf(stderr, _("Aha! \'%c\' (%d)\n"), kbinput,
460 kbinput);
Chris Allegretta658399a2001-06-14 02:54:22 +0000461#endif
Chris Allegretta5af58892003-01-17 21:07:38 +0000462 if (kbinput == t->val || kbinput == t->val - 32)
463 /* We hit an Alt key. Do like above. We don't
464 just ungetch() the letter and let it get
465 caught above cause that screws the
466 keypad... */
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000467 return t->val;
Chris Allegretta658399a2001-06-14 02:54:22 +0000468 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000469 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000470 break;
471
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000472 default:
473 if (kbinput < 32)
474 break;
Chris Allegretta6df90f52002-07-19 01:08:59 +0000475 answer = nrealloc(answer, xend + 2);
476 memmove(answer + x + 1, answer + x, xend - x + 1);
477 xend++;
478 answer[x] = kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000479 x++;
480
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000481#ifdef DEBUG
482 fprintf(stderr, _("input \'%c\' (%d)\n"), kbinput, kbinput);
483#endif
Chris Allegretta5beed502003-01-05 20:41:21 +0000484 } /* switch (kbinput) */
Chris Allegrettaa65ba512003-01-05 20:57:07 +0000485#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +0000486 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +0000487#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +0000488 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000489 wrefresh(bottomwin);
Chris Allegretta6df90f52002-07-19 01:08:59 +0000490 } /* while (kbinput ...) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000491
Chris Allegretta5af58892003-01-17 21:07:38 +0000492 /* We finished putting in an answer; reset x */
493 x = -1;
494
Chris Allegretta7662c862003-01-13 01:35:15 +0000495 /* Just check for a blank answer here */
Chris Allegretta15c28f82003-01-05 21:47:06 +0000496 if (answer[0] == '\0')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000497 return -2;
498 else
499 return 0;
500}
501
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000502/* If modified is not already set, set it and update titlebar. */
503void set_modified(void)
504{
505 if (!ISSET(MODIFIED)) {
506 SET(MODIFIED);
507 titlebar(NULL);
508 wrefresh(topwin);
509 }
510}
511
Chris Allegretta6df90f52002-07-19 01:08:59 +0000512void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000513{
514 int namelen, space;
Chris Allegretta6df90f52002-07-19 01:08:59 +0000515 const char *what = path;
Chris Allegrettaf4b96012001-01-03 07:11:47 +0000516
517 if (path == NULL)
518 what = filename;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000519
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000520 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +0000521
Chris Allegretta6df90f52002-07-19 01:08:59 +0000522 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyc5967552002-06-21 03:20:06 +0000523 mvwaddnstr(topwin, 0, 2, VERMSG, COLS - 3);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000524
Chris Allegretta6df90f52002-07-19 01:08:59 +0000525 space = COLS - sizeof(VERMSG) - 22;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000526
Chris Allegrettaf4b96012001-01-03 07:11:47 +0000527 namelen = strlen(what);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000528
David Lawrence Ramseyc5967552002-06-21 03:20:06 +0000529 if (space > 0) {
530 if (what[0] == '\0')
Chris Allegretta6df90f52002-07-19 01:08:59 +0000531 mvwaddnstr(topwin, 0, COLS / 2 - 6, _("New Buffer"),
532 COLS / 2 + COLS % 2 - 6);
533 else if (namelen > space) {
534 if (path == NULL)
535 waddstr(topwin, _(" File: ..."));
536 else
537 waddstr(topwin, _(" DIR: ..."));
538 waddstr(topwin, &what[namelen - space]);
539 } else {
540 if (path == NULL)
541 mvwaddstr(topwin, 0, COLS / 2 - (namelen / 2 + 1),
542 _("File: "));
543 else
544 mvwaddstr(topwin, 0, COLS / 2 - (namelen / 2 + 1),
545 _(" DIR: "));
546 waddstr(topwin, what);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000547 }
David Lawrence Ramseyc5967552002-06-21 03:20:06 +0000548 } /* If we don't have space, we shouldn't bother */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000549 if (ISSET(MODIFIED))
Chris Allegretta6df90f52002-07-19 01:08:59 +0000550 mvwaddnstr(topwin, 0, COLS - 11, _(" Modified "), 11);
Chris Allegretta4dc03d52002-05-11 03:04:44 +0000551 else if (ISSET(VIEW_MODE))
Chris Allegretta6df90f52002-07-19 01:08:59 +0000552 mvwaddnstr(topwin, 0, COLS - 11, _(" View "), 11);
Chris Allegretta8ce24132001-04-30 11:28:46 +0000553
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000554 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +0000555
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000556 wrefresh(topwin);
557 reset_cursor();
558}
559
Chris Allegretta6232d662002-05-12 19:52:15 +0000560void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000561{
Chris Allegrettabc72e362002-02-16 20:03:44 +0000562 int i, j, numcols;
Chris Allegretta3bbc4162003-01-23 00:46:12 +0000563 char keystr[9];
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000564 int slen;
565
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000566 if (ISSET(NO_HELP))
567 return;
568
Chris Allegretta6232d662002-05-12 19:52:15 +0000569 if (s == main_list) {
570 slen = MAIN_VISIBLE;
571 assert(MAIN_VISIBLE <= length_of_list(s));
572 } else
573 slen = length_of_list(s);
574
Chris Allegretta6232d662002-05-12 19:52:15 +0000575 /* There will be this many columns of shortcuts */
576 numcols = (slen + (slen % 2)) / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000577
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000578 blank_bottomwin();
Chris Allegretta658399a2001-06-14 02:54:22 +0000579
Chris Allegrettabc72e362002-02-16 20:03:44 +0000580 for (i = 0; i < numcols; i++) {
581 for (j = 0; j <= 1; j++) {
Chris Allegretta658399a2001-06-14 02:54:22 +0000582
Chris Allegretta6232d662002-05-12 19:52:15 +0000583 wmove(bottomwin, 1 + j, i * (COLS / numcols));
Chris Allegrettaa8c22572002-02-15 19:17:02 +0000584
Chris Allegretta5beed502003-01-05 20:41:21 +0000585 /* Yucky sentinel values we can't handle a better way */
Chris Allegretta6232d662002-05-12 19:52:15 +0000586 if (s->val == NANO_CONTROL_SPACE)
587 strcpy(keystr, "^ ");
Chris Allegrettaa65ba512003-01-05 20:57:07 +0000588#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +0000589 else if (s->val == KEY_UP)
Chris Allegretta3bbc4162003-01-23 00:46:12 +0000590 strncpy(keystr, _("Up"), 8);
Chris Allegretta5beed502003-01-05 20:41:21 +0000591#endif /* NANO_SMALL */
592 else if (s->val > 0) {
Chris Allegretta6232d662002-05-12 19:52:15 +0000593 if (s->val < 64)
594 sprintf(keystr, "^%c", s->val + 64);
595 else
596 sprintf(keystr, "M-%c", s->val - 32);
597 } else if (s->altval > 0)
598 sprintf(keystr, "M-%c", s->altval);
Chris Allegretta658399a2001-06-14 02:54:22 +0000599
Chris Allegretta6232d662002-05-12 19:52:15 +0000600 onekey(keystr, s->desc, COLS / numcols);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000601
Chris Allegretta6232d662002-05-12 19:52:15 +0000602 s = s->next;
603 if (s == NULL)
604 goto break_completely_out;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000605 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000606 }
607
Chris Allegretta6df90f52002-07-19 01:08:59 +0000608 break_completely_out:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000609 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000610}
611
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000612/* Write a shortcut key to the help area at the bottom of the window.
613 * keystroke is e.g. "^G" and desc is e.g. "Get Help".
614 * We are careful to write exactly len characters, even if len is
615 * very small and keystroke and desc are long. */
616void onekey(const char *keystroke, const char *desc, int len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000617{
Chris Allegretta5beed502003-01-05 20:41:21 +0000618
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000619 wattron(bottomwin, A_REVERSE);
620 waddnstr(bottomwin, keystroke, len);
621 wattroff(bottomwin, A_REVERSE);
622 len -= strlen(keystroke);
623 if (len > 0) {
624 waddch(bottomwin, ' ');
625 len--;
626 waddnstr(bottomwin, desc, len);
627 len -= strlen(desc);
628 for (; len > 0; len--)
629 waddch(bottomwin, ' ');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000630 }
631}
632
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000633/* And so start the display update routines. */
634
635#ifndef NDEBUG
636int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000637{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000638 int check_line = 0;
639 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000640
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000641 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
642 check_line++;
643 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +0000644}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000645#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +0000646
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000647 /* nano scrolls horizontally within a line in chunks. This function
648 * returns the column number of the first character displayed in the
649 * window when the cursor is at the given column. */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000650int get_page_start(int column)
Chris Allegretta6df90f52002-07-19 01:08:59 +0000651{
652 assert(COLS > 9);
653 return column < COLS - 1 ? 0 : column - 7 - (column - 8) % (COLS - 9);
654}
655
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000656/* Resets current_y, based on the position of current, and puts the
657 * cursor at (current_y, current_x). */
658void reset_cursor(void)
659{
660 const filestruct *ptr = edittop;
661 size_t x;
662
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000663 /* Yuck. This condition can be true after open_file() when opening
664 * the first file. */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +0000665 if (edittop == NULL)
666 return;
667
668 current_y = 0;
669
670 while (ptr != current && ptr != editbot && ptr->next != NULL) {
671 ptr = ptr->next;
672 current_y++;
673 }
674
675 x = xplustabs();
676 wmove(edit, current_y, x - get_page_start(x));
677}
Chris Allegretta6df90f52002-07-19 01:08:59 +0000678
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000679/* edit_add() takes care of the job of actually painting a line into
680 * the edit window. Called only from update_line(). Expects a
681 * converted-to-not-have-tabs line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000682void edit_add(const filestruct *fileptr, int yval, int start
683#ifndef NANO_SMALL
684 , int virt_mark_beginx, int virt_cur_x
685#endif
686 )
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000687{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000688#ifdef DEBUG
689 fprintf(stderr, "Painting line %d, current is %d\n", fileptr->lineno,
690 current->lineno);
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000691#endif
692
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000693 /* Just paint the string in any case (we'll add color or reverse on
Chris Allegretta598106e2002-01-19 01:59:37 +0000694 just the text that needs it */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000695 mvwaddnstr(edit, yval, 0, &fileptr->data[start], COLS);
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000696
Chris Allegretta7dd77682001-12-08 19:52:28 +0000697#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +0000698 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000699 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000700
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000701 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
702 int x_start;
703 /* Starting column for mvwaddnstr. Zero-based. */
704 int paintlen;
705 /* number of chars to paint on this line. There are COLS
706 * characters on a whole line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000707 regmatch_t startmatch; /* match position for start_regexp*/
708 regmatch_t endmatch; /* match position for end_regexp*/
709
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000710 if (tmpcolor->bright)
711 wattron(edit, A_BOLD);
712 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
713 /* Two notes about regexec. Return value 0 means there is a
714 * match. Also, rm_eo is the first non-matching character
715 * after the match. */
716
717 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000718 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000719 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000720
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000721 /* We increment k by rm_eo, to move past the end of the
722 last match. Even though two matches may overlap, we
723 want to ignore them, so that we can highlight C-strings
724 correctly. */
725 while (k < start + COLS) {
726 /* Note the fifth parameter to regexec. It says not to
727 * match the beginning-of-line character unless
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000728 * k == 0. If regexec returns nonzero, there are no
729 * more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +0000730 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000731 &startmatch, k == 0 ? 0 : REG_NOTBOL))
732 break;
733 /* Translate the match to the beginning of the line. */
734 startmatch.rm_so += k;
735 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +0000736 if (startmatch.rm_so == startmatch.rm_eo) {
737 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +0000738 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +0000739 } else if (startmatch.rm_so < start + COLS &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000740 startmatch.rm_eo > start) {
741 x_start = startmatch.rm_so - start;
742 if (x_start < 0)
743 x_start = 0;
744 paintlen = startmatch.rm_eo - start - x_start;
745 if (paintlen > COLS - x_start)
746 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000747
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000748 assert(0 <= x_start && 0 < paintlen &&
749 x_start + paintlen <= COLS);
750 mvwaddnstr(edit, yval, x_start,
751 fileptr->data + start + x_start, paintlen);
752 }
753 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +0000754 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000755 } else {
756 /* This is a multi-line regexp. There are two steps.
757 * First, we have to see if the beginning of the line is
758 * colored by a start on an earlier line, and an end on
759 * this line or later.
760 *
761 * We find the first line before fileptr matching the
762 * start. If every match on that line is followed by an
763 * end, then go to step two. Otherwise, find the next line
764 * after start_line matching the end. If that line is not
765 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +0000766
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000767 const filestruct *start_line = fileptr->prev;
768 /* the first line before fileptr matching start*/
769 regoff_t start_col;
770 /* where it starts in that line */
771 const filestruct *end_line;
772 int searched_later_lines = 0;
773 /* Used in step 2. Have we looked for an end on
774 * lines after fileptr? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000775
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000776 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +0000777 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000778 &startmatch, 0)) {
779 /* If there is an end on this line, there is no need
780 * to look for starts on earlier lines. */
Chris Allegrettace452fb2003-02-03 02:56:44 +0000781 if (!regexec(tmpcolor->end, start_line->data, 1,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000782 &endmatch, 0))
783 goto step_two;
784 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000785 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000786 /* No start found, so skip to the next step. */
787 if (start_line == NULL)
788 goto step_two;
789 /* Now start_line is the first line before fileptr
790 * containing a start match. Is there a start on this
791 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000792
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000793 start_col = 0;
794 while (1) {
795 start_col += startmatch.rm_so;
796 startmatch.rm_eo -= startmatch.rm_so;
Chris Allegrettace452fb2003-02-03 02:56:44 +0000797 if (regexec(tmpcolor->end,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000798 start_line->data + start_col + startmatch.rm_eo,
799 1, &endmatch,
800 start_col + startmatch.rm_eo == 0 ? 0 : REG_NOTBOL))
801 /* No end found after this start */
802 break;
803 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +0000804 if (regexec(&tmpcolor->start,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000805 start_line->data + start_col, 1, &startmatch,
806 REG_NOTBOL))
807 /* No later start on this line. */
808 goto step_two;
809 }
810 /* Indeed, there is a start not followed on this line by an
811 * end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000812
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000813 /* We have already checked that there is no end before
814 * fileptr and after the start. Is there an end after
815 * the start at all? We don't paint unterminated starts. */
816 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +0000817 while (end_line != NULL &&
818 regexec(tmpcolor->end, end_line->data, 1, &endmatch, 0))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000819 end_line = end_line->next;
820
821 /* No end found, or it is too early. */
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000822 if (end_line == NULL || end_line->lineno < fileptr->lineno ||
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000823 (end_line == fileptr && endmatch.rm_eo <= start))
824 goto step_two;
825
826 /* Now paint the start of fileptr. */
827 paintlen = end_line != fileptr
828 ? COLS : endmatch.rm_eo - start;
829 if (paintlen > COLS)
830 paintlen = COLS;
831
832 assert(0 < paintlen && paintlen <= COLS);
833 mvwaddnstr(edit, yval, 0, fileptr->data + start, paintlen);
834
835 /* We have already painted the whole line. */
836 if (paintlen == COLS)
837 goto skip_step_two;
838
839
840 step_two: /* Second step, we look for starts on this line. */
841 start_col = 0;
842 while (start_col < start + COLS) {
Chris Allegrettace452fb2003-02-03 02:56:44 +0000843 if (regexec(&tmpcolor->start, fileptr->data + start_col, 1,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000844 &startmatch, start_col == 0 ? 0 : REG_NOTBOL)
845 || start_col + startmatch.rm_so >= start + COLS)
846 /* No more starts on this line. */
847 break;
848 /* Translate the match to be relative to the
849 * beginning of the line. */
850 startmatch.rm_so += start_col;
851 startmatch.rm_eo += start_col;
852
853 x_start = startmatch.rm_so - start;
854 if (x_start < 0) {
855 x_start = 0;
856 startmatch.rm_so = start;
857 }
Chris Allegrettace452fb2003-02-03 02:56:44 +0000858 if (!regexec(tmpcolor->end, fileptr->data + startmatch.rm_eo,
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000859 1, &endmatch,
860 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL)) {
861 /* Translate the end match to be relative to the
862 beginning of the line. */
863 endmatch.rm_so += startmatch.rm_eo;
864 endmatch.rm_eo += startmatch.rm_eo;
865 /* There is an end on this line. But does it
866 appear on this page, and is the match more than
867 zero characters long? */
868 if (endmatch.rm_eo > start &&
869 endmatch.rm_eo > startmatch.rm_so) {
870 paintlen = endmatch.rm_eo - start - x_start;
871 if (x_start + paintlen > COLS)
872 paintlen = COLS - x_start;
873
874 assert(0 <= x_start && 0 < paintlen &&
875 x_start + paintlen <= COLS);
876 mvwaddnstr(edit, yval, x_start,
877 fileptr->data + start + x_start, paintlen);
878 }
879 } else if (!searched_later_lines) {
880 searched_later_lines = 1;
881 /* There is no end on this line. But we haven't
882 * yet looked for one on later lines. */
883 end_line = fileptr->next;
Chris Allegrettace452fb2003-02-03 02:56:44 +0000884 while (end_line != NULL && regexec(tmpcolor->end,
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000885 end_line->data, 1, &endmatch, 0))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000886 end_line = end_line->next;
887 if (end_line != NULL) {
888 assert(0 <= x_start && x_start < COLS);
889 mvwaddnstr(edit, yval, x_start,
890 fileptr->data + start + x_start,
891 COLS - x_start);
892 /* We painted to the end of the line, so
893 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000894 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +0000895 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000896 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000897 start_col = startmatch.rm_so + 1;
898 } /* while start_col < start + COLS */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000899 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +0000900
Chris Allegrettace452fb2003-02-03 02:56:44 +0000901 skip_step_two:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000902 wattroff(edit, A_BOLD);
903 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
904 } /* for tmpcolor in colorstrings */
905 }
Chris Allegretta598106e2002-01-19 01:59:37 +0000906#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000907
Chris Allegretta7dd77682001-12-08 19:52:28 +0000908#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000909 if (ISSET(MARK_ISSET)
910 && (fileptr->lineno <= mark_beginbuf->lineno
911 || fileptr->lineno <= current->lineno)
912 && (fileptr->lineno >= mark_beginbuf->lineno
913 || fileptr->lineno >= current->lineno)) {
914 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +0000915
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000916 int x_start;
917 /* Starting column for mvwaddnstr. Zero-based. */
918 int paintlen;
919 /* number of chars to paint on this line. There are COLS
920 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +0000921
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000922 if (mark_beginbuf == fileptr && current == fileptr) {
923 x_start = virt_mark_beginx < virt_cur_x ? virt_mark_beginx
924 : virt_cur_x;
925 paintlen = abs(virt_mark_beginx - virt_cur_x);
926 } else {
927 if (mark_beginbuf->lineno < fileptr->lineno ||
928 current->lineno < fileptr->lineno)
929 x_start = 0;
930 else
931 x_start = mark_beginbuf == fileptr ? virt_mark_beginx
932 : virt_cur_x;
933
934 if (mark_beginbuf->lineno > fileptr->lineno ||
935 current->lineno > fileptr->lineno)
936 paintlen = start + COLS;
937 else
938 paintlen = mark_beginbuf == fileptr ? virt_mark_beginx
939 : virt_cur_x;
940 }
941 x_start -= start;
942 if (x_start < 0) {
943 paintlen += x_start;
944 x_start = 0;
945 }
946 if (x_start + paintlen > COLS)
947 paintlen = COLS - x_start;
948 if (paintlen > 0) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000949 wattron(edit, A_REVERSE);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000950 assert(x_start >= 0 && paintlen > 0 && x_start + paintlen <= COLS);
951 mvwaddnstr(edit, yval, x_start,
952 fileptr->data + start + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000953 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000954 }
Chris Allegretta08893e02001-11-29 02:42:27 +0000955 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000956#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000957}
958
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000959/* Just update one line in the edit buffer. Basically a wrapper for
960 * edit_add(). If fileptr != current, then index is considered 0.
961 * The line will be displayed starting with fileptr->data[index].
962 * Likely args are current_x or 0. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +0000963void update_line(filestruct *fileptr, int index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000964{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000965 int line;
966 /* line in the edit window for CURSES calls */
967#ifndef NANO_SMALL
968 int virt_cur_x;
969 int virt_mark_beginx;
970#endif
971 char *original;
972 /* The original string fileptr->data. */
973 char *converted;
974 /* fileptr->data converted to have tabs and control characters
975 * expanded. */
976 size_t pos;
977 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000978
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +0000979 if (fileptr == NULL)
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000980 return;
Robert Siemborski53154a72000-06-18 00:11:03 +0000981
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000982 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000983
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000984 /* We assume the line numbers are valid. Is that really true? */
985 assert(line < 0 || line == check_linenumbers(fileptr));
986
987 if (line < 0 || line >= editwinrows)
988 return;
989
990 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000991 mvwaddstr(edit, line, 0, hblank);
992
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000993 original = fileptr->data;
994 converted = charalloc(strlenpt(original) + 1);
Chris Allegretta5beed502003-01-05 20:41:21 +0000995
996 /* Next, convert all the tabs to spaces, so everything else is easy.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +0000997 * Note the internal speller sends us index == -1. */
998 index = fileptr == current && index > 0 ? strnlenpt(original, index) : 0;
999#ifndef NANO_SMALL
1000 virt_cur_x = fileptr == current ? strnlenpt(original, current_x) : current_x;
1001 virt_mark_beginx = fileptr == mark_beginbuf ? strnlenpt(original, mark_beginx) : mark_beginx;
1002#endif
Robert Siemborski53875912000-06-16 04:25:30 +00001003
1004 pos = 0;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001005 for (; *original != '\0'; original++) {
1006 if (*original == '\t')
Robert Siemborski53875912000-06-16 04:25:30 +00001007 do {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001008 converted[pos++] = ' ';
Chris Allegretta6d690a32000-08-03 22:51:21 +00001009 } while (pos % tabsize);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001010 else if (is_cntrl_char(*original)) {
1011 converted[pos++] = '^';
1012 if (*original == 127)
1013 converted[pos++] = '?';
1014 else if (*original == '\n')
1015 /* Treat newlines (ASCII 10's) embedded in a line as encoded
1016 * nulls (ASCII 0's); the line in question should be run
1017 * through unsunder() before reaching here */
1018 converted[pos++] = '@';
1019 else
1020 converted[pos++] = *original + 64;
1021 } else
1022 converted[pos++] = *original;
Robert Siemborski53875912000-06-16 04:25:30 +00001023 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001024 converted[pos] = '\0';
Robert Siemborski53875912000-06-16 04:25:30 +00001025
Chris Allegretta4dc03d52002-05-11 03:04:44 +00001026 /* Now, paint the line */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001027 original = fileptr->data;
1028 fileptr->data = converted;
1029 page_start = get_page_start(index);
1030 edit_add(fileptr, line, page_start
1031#ifndef NANO_SMALL
1032 , virt_mark_beginx, virt_cur_x
1033#endif
1034 );
1035 free(converted);
1036 fileptr->data = original;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001037
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001038 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001039 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00001040 if (pos > page_start + COLS)
1041 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001042}
1043
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001044/* This function updates current, based on where current_y is;
1045 * reset_cursor() does the opposite. */
1046void update_cursor(void)
1047{
1048 int i = 0;
1049
1050#ifdef DEBUG
1051 fprintf(stderr, _("Moved to (%d, %d) in edit buffer\n"), current_y,
1052 current_x);
1053#endif
1054
1055 current = edittop;
1056 while (i < current_y && current->next != NULL) {
1057 current = current->next;
1058 i++;
1059 }
1060
1061#ifdef DEBUG
Chris Allegretta0e86e602003-01-23 04:27:23 +00001062 fprintf(stderr, "current->data = \"%s\"\n", current->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001063#endif
1064}
1065
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001066void center_cursor(void)
1067{
1068 current_y = editwinrows / 2;
1069 wmove(edit, current_y, current_x);
1070}
1071
Chris Allegretta6df90f52002-07-19 01:08:59 +00001072/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001073void edit_refresh(void)
1074{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001075 /* Neither of these conditions should occur, but they do. edittop is
1076 * NULL when you open an existing file on the command line, and
1077 * ENABLE_COLOR is defined. Yuck. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001078 if (current == NULL)
1079 return;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001080 if (edittop == NULL)
1081 edittop = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001082
Chris Allegretta63d0b482003-01-26 19:47:10 +00001083 if (current->lineno < edittop->lineno ||
1084 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001085 /* Note that edit_update() changes edittop so that
1086 * current->lineno = edittop->lineno + editwinrows / 2. Thus
1087 * when it then calls edit_refresh(), there is no danger of
1088 * getting an infinite loop. */
Chris Allegrettada721be2000-07-31 01:26:42 +00001089 edit_update(current, CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001090 else {
1091 int nlines = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001092
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001093 /* Don't make the cursor jump around the screen whilst updating */
1094 leaveok(edit, TRUE);
1095
1096 editbot = edittop;
1097 while (nlines < editwinrows) {
1098 update_line(editbot, current_x);
1099 nlines++;
1100 if (editbot->next == NULL)
1101 break;
1102 editbot = editbot->next;
1103 }
1104 while (nlines < editwinrows) {
1105 mvwaddstr(edit, nlines, 0, hblank);
1106 nlines++;
1107 }
1108 /* What the hell are we expecting to update the screen if this
Chris Allegretta7662c862003-01-13 01:35:15 +00001109 isn't here? Luck? */
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001110 wrefresh(edit);
1111 leaveok(edit, FALSE);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001112 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001113}
1114
Chris Allegretta7662c862003-01-13 01:35:15 +00001115/* Same as above, but touch the window first, so everything is
1116 * redrawn. */
Chris Allegrettaf1d33d32000-08-19 03:53:39 +00001117void edit_refresh_clearok(void)
1118{
1119 clearok(edit, TRUE);
1120 edit_refresh();
1121 clearok(edit, FALSE);
1122}
1123
1124/*
Chris Allegretta88520c92001-05-05 17:45:54 +00001125 * Nice generic routine to update the edit buffer, given a pointer to the
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001126 * file struct =)
1127 */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001128void edit_update(filestruct *fileptr, topmidbotnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001129{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001130 if (fileptr == NULL)
1131 return;
1132
Chris Allegretta6df90f52002-07-19 01:08:59 +00001133 if (location != TOP) {
1134 int goal = location == NONE ? current_y - 1 : editwinrows / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001135
Chris Allegretta6df90f52002-07-19 01:08:59 +00001136 for (; goal >= 0 && fileptr->prev != NULL; goal--)
1137 fileptr = fileptr->prev;
1138 }
1139 edittop = fileptr;
Robert Siemborski29e9a762000-07-05 03:16:04 +00001140 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001141
1142 edit_refresh();
1143}
1144
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001145/*
1146 * Ask a question on the statusbar. Answer will be stored in answer
1147 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
Chris Allegretta88520c92001-05-05 17:45:54 +00001148 * otherwise, the valid shortcut key caught. Def is any editable text we
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001149 * want to put up by default.
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00001150 *
1151 * New arg tabs tells whether or not to allow tab completion.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001152 */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001153int statusq(int tabs, const shortcut *s, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00001154#ifndef NANO_SMALL
1155 historyheadtype *which_history,
1156#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001157 const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001158{
1159 va_list ap;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001160 char *foo = charalloc(COLS - 3);
Chris Allegretta9caa1932002-02-15 20:08:05 +00001161 int ret;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001162#ifndef DISABLE_TABCOMP
Chris Allegrettaa16e4e92002-01-05 18:59:54 +00001163 int list = 0;
Chris Allegretta2084acc2001-11-29 03:43:08 +00001164#endif
Chris Allegretta47fcfe52003-01-26 21:01:16 +00001165 static int resetpos = 0; /* Do we need to scrap the cursor position
1166 on the statusbar? */
Chris Allegretta2084acc2001-11-29 03:43:08 +00001167
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001168 bottombars(s);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001169
1170 va_start(ap, msg);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001171 vsnprintf(foo, COLS - 4, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001172 va_end(ap);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001173 foo[COLS - 4] = '\0';
Chris Allegretta8ce24132001-04-30 11:28:46 +00001174
Chris Allegretta5beed502003-01-05 20:41:21 +00001175 ret = nanogetstr(tabs, foo, def,
1176#ifndef NANO_SMALL
1177 which_history,
Chris Allegretta2084acc2001-11-29 03:43:08 +00001178#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00001179 s
1180#ifndef DISABLE_TABCOMP
1181 , &list
1182#endif
Chris Allegretta47fcfe52003-01-26 21:01:16 +00001183 , resetpos);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001184 free(foo);
Chris Allegretta47fcfe52003-01-26 21:01:16 +00001185 resetpos = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001186
1187 switch (ret) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001188 case NANO_FIRSTLINE_KEY:
1189 do_first_line();
Chris Allegretta47fcfe52003-01-26 21:01:16 +00001190 resetpos = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001191 break;
1192 case NANO_LASTLINE_KEY:
1193 do_last_line();
Chris Allegretta47fcfe52003-01-26 21:01:16 +00001194 resetpos = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001195 break;
1196 case NANO_CANCEL_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001197 ret = -1;
Chris Allegretta47fcfe52003-01-26 21:01:16 +00001198 resetpos = 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001199 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001200 }
Chris Allegrettaa90d0cf2003-02-10 02:55:03 +00001201 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001202
1203#ifdef DEBUG
1204 fprintf(stderr, _("I got \"%s\"\n"), answer);
1205#endif
1206
Chris Allegretta6df90f52002-07-19 01:08:59 +00001207#ifndef DISABLE_TABCOMP
1208 /* if we've done tab completion, there might be a list of
1209 filename matches on the edit window at this point; make sure
1210 they're cleared off */
1211 if (list)
1212 edit_refresh();
1213#endif
1214
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001215 return ret;
1216}
1217
1218/*
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001219 * Ask a simple yes/no question on the statusbar. Returns 1 for Y, 0
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001220 * for N, 2 for All (if all is nonzero when passed in) and -1 for abort
1221 * (^C).
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001222 */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001223int do_yesno(int all, int leavecursor, const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001224{
1225 va_list ap;
Chris Allegrettadb28e962003-01-28 01:23:40 +00001226 char *foo;
1227 int ok = -2;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001228 const char *yesstr; /* String of yes characters accepted */
1229 const char *nostr; /* Same for no */
1230 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00001231
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001232 /* Yes, no and all are strings of any length. Each string consists of
Chris Allegretta598106e2002-01-19 01:59:37 +00001233 all characters accepted as a valid character for that value.
1234 The first value will be the one displayed in the shortcuts. */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001235 yesstr = _("Yy");
1236 nostr = _("Nn");
1237 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001238
Jordi Mallach0b0fc492000-06-23 01:00:13 +00001239 /* Remove gettext call for keybindings until we clear the thing up */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001240 if (!ISSET(NO_HELP)) {
Chris Allegretta6232d662002-05-12 19:52:15 +00001241 char shortstr[3]; /* Temp string for Y, N, A */
1242
Chris Allegrettadb28e962003-01-28 01:23:40 +00001243 /* Write the bottom of the screen */
1244 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001245
Chris Allegretta6232d662002-05-12 19:52:15 +00001246 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00001247 wmove(bottomwin, 1, 0);
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001248 onekey(shortstr, _("Yes"), 16);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001249
1250 if (all) {
Chris Allegrettadb28e962003-01-28 01:23:40 +00001251 wmove(bottomwin, 1, 16);
Chris Allegretta6232d662002-05-12 19:52:15 +00001252 shortstr[1] = allstr[0];
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001253 onekey(shortstr, _("All"), 16);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001254 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001255
Chris Allegrettadb28e962003-01-28 01:23:40 +00001256 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00001257 shortstr[1] = nostr[0];
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001258 onekey(shortstr, _("No"), 16);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001259
Chris Allegrettadb28e962003-01-28 01:23:40 +00001260 wmove(bottomwin, 2, 16);
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001261 onekey("^C", _("Cancel"), 16);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001262 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00001263
1264 foo = charalloc(COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001265 va_start(ap, msg);
Chris Allegrettadb28e962003-01-28 01:23:40 +00001266 vsnprintf(foo, COLS, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001267 va_end(ap);
Chris Allegrettadb28e962003-01-28 01:23:40 +00001268 foo[COLS - 1] = '\0';
Chris Allegretta8ce24132001-04-30 11:28:46 +00001269
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001270 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001271
1272 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001273 mvwaddstr(bottomwin, 0, 0, foo);
Chris Allegrettadb28e962003-01-28 01:23:40 +00001274 free(foo);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001275
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001276 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001277
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001278 wrefresh(bottomwin);
1279
Chris Allegrettadb28e962003-01-28 01:23:40 +00001280 do {
1281 int kbinput = wgetch(edit);
1282#ifndef DISABLE_MOUSE
1283 MEVENT mevent;
Chris Allegretta235ab192001-04-12 13:24:40 +00001284#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001285
Chris Allegrettadb28e962003-01-28 01:23:40 +00001286 if (kbinput == NANO_CONTROL_C)
1287 ok = -1;
1288#ifndef DISABLE_MOUSE
1289 /* Look ma! We get to duplicate lots of code from do_mouse!! */
1290 else if (kbinput == KEY_MOUSE && getmouse(&mevent) != ERR &&
1291 wenclose(bottomwin, mevent.y, mevent.x) &&
1292 !ISSET(NO_HELP) && mevent.x < 32 &&
1293 mevent.y >= editwinrows + 3) {
1294 int x = mevent.x /= 16;
1295 /* Did we click in the first column of shortcuts, or the
1296 second? */
1297 int y = mevent.y - editwinrows - 3;
1298 /* Did we click in the first row of shortcuts? */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001299
Chris Allegrettadb28e962003-01-28 01:23:40 +00001300 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
1301 /* x = 0 means they clicked Yes or No.
1302 y = 0 means Yes or All. */
1303 ok = -2 * x * y + x - y + 1;
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00001304
Chris Allegrettadb28e962003-01-28 01:23:40 +00001305 if (ok == 2 && !all)
1306 ok = -2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001307 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00001308#endif
1309 /* Look for the kbinput in the yes, no and (optionally) all str */
1310 else if (strchr(yesstr, kbinput) != NULL)
1311 ok = 1;
1312 else if (strchr(nostr, kbinput) != NULL)
1313 ok = 0;
1314 else if (all && strchr(allstr, kbinput) != NULL)
1315 ok = 2;
1316 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001317
Chris Allegrettadb28e962003-01-28 01:23:40 +00001318 /* Then blank the statusbar. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001319 blank_statusbar_refresh();
1320
Chris Allegrettadb28e962003-01-28 01:23:40 +00001321 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001322}
1323
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001324int total_refresh(void)
1325{
1326 clearok(edit, TRUE);
1327 clearok(topwin, TRUE);
1328 clearok(bottomwin, TRUE);
1329 wnoutrefresh(edit);
1330 wnoutrefresh(topwin);
1331 wnoutrefresh(bottomwin);
1332 doupdate();
1333 clearok(edit, FALSE);
1334 clearok(topwin, FALSE);
1335 clearok(bottomwin, FALSE);
1336 edit_refresh();
1337 titlebar(NULL);
1338 return 1;
1339}
1340
1341void display_main_list(void)
1342{
1343 bottombars(main_list);
1344}
1345
Chris Allegretta6df90f52002-07-19 01:08:59 +00001346void statusbar(const char *msg, ...)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001347{
1348 va_list ap;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001349 char *foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001350 int start_x = 0;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001351 size_t foo_len;
1352
Chris Allegrettaa0d89972003-02-03 03:32:08 +00001353 va_start(ap, msg);
1354
1355 /* Curses mode is turned off. If we use wmove() now, it will muck up
1356 the terminal settings. So we just use vfprintf(). */
1357 if (curses_ended) {
1358 vfprintf(stderr, msg, ap);
1359 va_end(ap);
1360 return;
1361 }
1362
Chris Allegretta6df90f52002-07-19 01:08:59 +00001363 assert(COLS >= 4);
1364 foo = charalloc(COLS - 3);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001365
Chris Allegretta6df90f52002-07-19 01:08:59 +00001366 vsnprintf(foo, COLS - 3, msg, ap);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001367 va_end(ap);
1368
Chris Allegretta6df90f52002-07-19 01:08:59 +00001369 foo[COLS - 4] = '\0';
1370 foo_len = strlen(foo);
1371 start_x = (COLS - foo_len - 4) / 2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001372
1373 /* Blank out line */
1374 blank_statusbar();
1375
1376 wmove(bottomwin, 0, start_x);
1377
1378 wattron(bottomwin, A_REVERSE);
1379
1380 waddstr(bottomwin, "[ ");
1381 waddstr(bottomwin, foo);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001382 free(foo);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001383 waddstr(bottomwin, " ]");
Chris Allegretta8ce24132001-04-30 11:28:46 +00001384
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001385 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00001386
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001387 wrefresh(bottomwin);
1388
Chris Allegrettad26ab912003-01-28 01:16:47 +00001389 SET(DISABLE_CURPOS);
1390 statblank = 26;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001391}
1392
Chris Allegrettad26ab912003-01-28 01:16:47 +00001393/*
1394 * If constant is false, the user typed ^C so we unconditionally display
1395 * the cursor position. Otherwise, we display it only if the character
1396 * position changed, and DISABLE_CURPOS is not set.
1397 *
1398 * If constant and DISABLE_CURPOS is set, we unset it and update old_i and
1399 * old_totsize. That way, we leave the current statusbar alone, but next
1400 * time we will display. */
Chris Allegretta2084acc2001-11-29 03:43:08 +00001401int do_cursorpos(int constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001402{
Chris Allegrettad26ab912003-01-28 01:16:47 +00001403 const filestruct *fileptr;
1404 unsigned long i = 0;
1405 static unsigned long old_i = 0;
1406 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001407
Chris Allegrettad26ab912003-01-28 01:16:47 +00001408 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00001409
1410 if (old_totsize == -1)
1411 old_totsize = totsize;
1412
Chris Allegrettad26ab912003-01-28 01:16:47 +00001413 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
1414 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001415 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00001416 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00001417 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00001418
Chris Allegrettad26ab912003-01-28 01:16:47 +00001419 if (constant && ISSET(DISABLE_CURPOS)) {
1420 UNSET(DISABLE_CURPOS);
1421 old_i = i;
1422 old_totsize = totsize;
1423 return 0;
1424 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00001425
Chris Allegrettad26ab912003-01-28 01:16:47 +00001426 /* if constant is false, display the position on the statusbar
Chris Allegretta2084acc2001-11-29 03:43:08 +00001427 unconditionally; otherwise, only display the position when the
1428 character values have changed */
Chris Allegrettad26ab912003-01-28 01:16:47 +00001429 if (!constant || old_i != i || old_totsize != totsize) {
1430 unsigned long xpt = xplustabs() + 1;
1431 unsigned long cur_len = strlenpt(current->data) + 1;
1432 int linepct = 100 * current->lineno / totlines;
1433 int colpct = 100 * xpt / cur_len;
1434 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
1435
1436 statusbar(
1437 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
1438 current->lineno, totlines, linepct,
1439 xpt, cur_len, colpct,
1440 i, totsize, bytepct);
1441 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00001442 }
1443
1444 old_i = i;
1445 old_totsize = totsize;
1446
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001447 reset_cursor();
Chris Allegrettad26ab912003-01-28 01:16:47 +00001448 return 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001449}
1450
Chris Allegretta2084acc2001-11-29 03:43:08 +00001451int do_cursorpos_void(void)
1452{
1453 return do_cursorpos(0);
1454}
1455
Chris Allegretta4640fe32003-02-10 03:10:03 +00001456/* Calculate the next line of help_text, starting at ptr. */
1457int line_len(const char *ptr)
1458{
1459 int j = 0;
1460
1461 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
1462 ptr++;
1463 j++;
1464 }
1465 if (j == COLS - 5) {
1466 /* Don't wrap at the first of two spaces following a period. */
1467 if (*ptr == ' ' && *(ptr + 1) == ' ')
1468 j++;
1469 /* Don't print half a word if we've run out of space */
1470 while (*ptr != ' ' && j > 0) {
1471 ptr--;
1472 j--;
1473 }
1474 /* Word longer than COLS - 5 chars just gets broken */
1475 if (j == 0)
1476 j = COLS - 5;
1477 }
1478 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
1479 return j;
1480}
1481
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001482/* Our shortcut-list-compliant help function, which is
1483 * better than nothing, and dynamic! */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001484int do_help(void)
1485{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001486#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00001487 int i, page = 0, kbinput = 0, no_more = 0, kp, kp2;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001488 int no_help_flag = 0;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001489 const shortcut *oldshortcut;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001490
1491 blank_edit();
1492 curs_set(0);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001493 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001494 blank_statusbar();
1495
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001496 /* set help_text as the string to display */
Chris Allegrettab3655b42001-10-22 03:15:31 +00001497 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001498 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001499
1500 oldshortcut = currshortcut;
Chris Allegrettab3655b42001-10-22 03:15:31 +00001501
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001502 currshortcut = help_list;
Chris Allegretta6fe61492001-05-21 12:56:25 +00001503
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001504 kp = keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001505 kp2 = keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001506
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001507 if (ISSET(NO_HELP)) {
1508
Chris Allegretta88520c92001-05-05 17:45:54 +00001509 /* Well, if we're going to do this, we should at least
Chris Allegretta70444892001-01-07 23:02:02 +00001510 do it the right way */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001511 no_help_flag = 1;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001512 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00001513 window_init();
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001514 bottombars(help_list);
Chris Allegretta70444892001-01-07 23:02:02 +00001515
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001516 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001517 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001518
1519 do {
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001520 const char *ptr = help_text;
1521
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001522 switch (kbinput) {
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001523#if !defined(DISABLE_MOUSE) && defined(NCURSES_MOUSE_VERSION)
Chris Allegretta598106e2002-01-19 01:59:37 +00001524 case KEY_MOUSE:
1525 do_mouse();
1526 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001527#endif
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001528 case 27:
1529 kbinput = wgetch(edit);
1530 switch(kbinput) {
1531 case '[':
1532 kbinput = wgetch(edit);
1533 switch(kbinput) {
1534 case '5': /* Alt-[-5 = Page Up */
1535 wgetch(edit);
1536 goto do_pageupkey;
1537 break;
1538 case 'V': /* Alt-[-V = Page Up in Hurd Console */
1539 case 'I': /* Alt-[-I = Page Up - FreeBSD Console */
1540 goto do_pageupkey;
1541 break;
1542 case '6': /* Alt-[-6 = Page Down */
1543 wgetch(edit);
1544 goto do_pagedownkey;
1545 break;
1546 case 'U': /* Alt-[-U = Page Down in Hurd Console */
1547 case 'G': /* Alt-[-G = Page Down - FreeBSD Console */
1548 goto do_pagedownkey;
1549 break;
1550 }
1551 break;
1552 }
1553 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001554 case NANO_NEXTPAGE_KEY:
1555 case NANO_NEXTPAGE_FKEY:
1556 case KEY_NPAGE:
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001557 do_pagedownkey:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001558 if (!no_more) {
1559 blank_edit();
1560 page++;
1561 }
1562 break;
1563 case NANO_PREVPAGE_KEY:
1564 case NANO_PREVPAGE_FKEY:
1565 case KEY_PPAGE:
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001566 do_pageupkey:
Chris Allegretta4640fe32003-02-10 03:10:03 +00001567 if (page > 0) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001568 no_more = 0;
1569 blank_edit();
1570 page--;
1571 }
1572 break;
1573 }
1574
Chris Allegretta88520c92001-05-05 17:45:54 +00001575 /* Calculate where in the text we should be, based on the page */
Chris Allegretta4640fe32003-02-10 03:10:03 +00001576 for (i = 1; i < page * (editwinrows - 1); i++) {
1577 ptr += line_len(ptr);
1578 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001579 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001580 }
1581
Chris Allegretta4640fe32003-02-10 03:10:03 +00001582 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
1583 int j = line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001584
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001585 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00001586 ptr += j;
1587 if (*ptr == '\n')
1588 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001589 }
Chris Allegretta4640fe32003-02-10 03:10:03 +00001590
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001591 if (*ptr == '\0') {
1592 no_more = 1;
1593 continue;
1594 }
Chris Allegretta598106e2002-01-19 01:59:37 +00001595 } while ((kbinput = wgetch(edit)) != NANO_EXIT_KEY &&
1596 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00001597
Chris Allegrettab3655b42001-10-22 03:15:31 +00001598 currshortcut = oldshortcut;
Chris Allegrettab3655b42001-10-22 03:15:31 +00001599
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001600 if (no_help_flag) {
Chris Allegretta70444892001-01-07 23:02:02 +00001601 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001602 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001603 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00001604 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00001605 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001606 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001607
1608 curs_set(1);
1609 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001610 kp = keypad_on(edit, kp);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001611 kp2 = keypad_on(bottomwin, kp2);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001612
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00001613 /* The help_init() at the beginning allocated help_text, which has
1614 now been written to screen. */
1615 free(help_text);
1616 help_text = NULL;
1617
Chris Allegretta6df90f52002-07-19 01:08:59 +00001618#elif defined(DISABLE_HELP)
1619 nano_disabled_msg();
1620#endif
1621
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001622 return 1;
1623}
1624
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00001625int keypad_on(WINDOW *win, int newval)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001626{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001627/* This is taken right from aumix. Don't sue me. */
1628#ifdef HAVE_USEKEYPAD
1629 int old = win->_use_keypad;
1630 keypad(win, newval);
1631 return old;
1632#else
1633 keypad(win, newval);
1634 return 1;
1635#endif /* HAVE_USEKEYPAD */
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001636}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001637
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001638/* Highlight the current word being replaced or spell checked. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001639void do_replace_highlight(int highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00001640{
1641 char *highlight_word = NULL;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001642 int x, y, word_len;
Chris Allegrettafb62f732000-12-05 11:36:41 +00001643
Chris Allegretta598106e2002-01-19 01:59:37 +00001644 highlight_word =
1645 mallocstrcpy(highlight_word, &current->data[current_x]);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001646
1647#ifdef HAVE_REGEX_H
1648 if (ISSET(USE_REGEXP))
1649 /* if we're using regexps, the highlight is the length of the
1650 search result, not the length of the regexp string */
1651 word_len = regmatches[0].rm_eo - regmatches[0].rm_so;
1652 else
1653#endif
1654 word_len = strlen(word);
1655
1656 highlight_word[word_len] = '\0';
Chris Allegrettafb62f732000-12-05 11:36:41 +00001657
Chris Allegretta88520c92001-05-05 17:45:54 +00001658 /* adjust output when word extends beyond screen */
Chris Allegrettafb62f732000-12-05 11:36:41 +00001659
1660 x = xplustabs();
Chris Allegretta6df90f52002-07-19 01:08:59 +00001661 y = get_page_start(x) + COLS;
Chris Allegrettafb62f732000-12-05 11:36:41 +00001662
Chris Allegretta6df90f52002-07-19 01:08:59 +00001663 if ((COLS - (y - x) + word_len) > COLS) {
Chris Allegrettafb62f732000-12-05 11:36:41 +00001664 highlight_word[y - x - 1] = '$';
1665 highlight_word[y - x] = '\0';
1666 }
1667
1668 /* OK display the output */
1669
1670 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00001671
Chris Allegrettafb62f732000-12-05 11:36:41 +00001672 if (highlight_flag)
1673 wattron(edit, A_REVERSE);
1674
1675 waddstr(edit, highlight_word);
1676
1677 if (highlight_flag)
1678 wattroff(edit, A_REVERSE);
1679
1680 free(highlight_word);
1681}
1682
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001683/* Fix editbot, based on the assumption that edittop is correct. */
1684void fix_editbot(void)
1685{
1686 int i;
1687
1688 editbot = edittop;
1689 for (i = 0; i < editwinrows && editbot->next != NULL; i++)
1690 editbot = editbot->next;
1691}
1692
1693#ifdef DEBUG
1694/* Dump the current file structure to stderr */
1695void dump_buffer(const filestruct *inptr) {
1696 if (inptr == fileage)
1697 fprintf(stderr, _("Dumping file buffer to stderr...\n"));
1698 else if (inptr == cutbuffer)
1699 fprintf(stderr, _("Dumping cutbuffer to stderr...\n"));
1700 else
1701 fprintf(stderr, _("Dumping a buffer to stderr...\n"));
1702
1703 while (inptr != NULL) {
1704 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
1705 inptr = inptr->next;
1706 }
1707}
1708#endif /* DEBUG */
1709
1710#ifdef DEBUG
1711void dump_buffer_reverse(void) {
1712 const filestruct *fileptr = filebot;
1713
1714 while (fileptr != NULL) {
1715 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
1716 fileptr = fileptr->prev;
1717 }
1718}
1719#endif /* DEBUG */
1720
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001721#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00001722#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001723#define XLCREDIT_LEN 8
1724
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001725void do_credits(void)
1726{
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001727 int i, j = 0, k, place = 0, start_x;
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001728
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +00001729 const char *what;
1730 const char *xlcredits[XLCREDIT_LEN];
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001731
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +00001732 const char *credits[CREDIT_LEN] = {
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001733 "0", /* "The nano text editor" */
1734 "1", /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001735 VERSION,
1736 "",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001737 "2", /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001738 "Chris Allegretta",
1739 "Jordi Mallach",
1740 "Adam Rogoyski",
1741 "Rob Siemborski",
1742 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001743 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00001744 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00001745 "Ken Tyler",
1746 "Sven Guckes",
1747 "Florian König",
1748 "Pauli Virtanen",
1749 "Daniele Medri",
1750 "Clement Laforet",
1751 "Tedi Heriyanto",
1752 "Bill Soudan",
1753 "Christian Weisgerber",
1754 "Erik Andersen",
1755 "Big Gaute",
1756 "Joshua Jensen",
1757 "Ryan Krebs",
1758 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00001759 "",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001760 "3", /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001761 "Plattsburgh State University",
1762 "Benet Laboratories",
1763 "Amy Allegretta",
1764 "Linda Young",
1765 "Jeremy Robichaud",
1766 "Richard Kolb II",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001767 "4", /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001768 "Linus Torvalds",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001769 "5", /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00001770 "Thomas Dickey",
1771 "Pavel Curtis",
1772 "Zeyd Ben-Halim",
1773 "Eric S. Raymond",
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001774 "6", /* "and anyone else we forgot..." */
1775 "7", /* "Thank you for using nano!\n" */
Chris Allegretta598106e2002-01-19 01:59:37 +00001776 "", "", "", "",
1777 "(c) 1999-2002 Chris Allegretta",
1778 "", "", "", "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00001779 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001780 };
1781
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001782 xlcredits[0] = _("The nano text editor");
1783 xlcredits[1] = _("version ");
1784 xlcredits[2] = _("Brought to you by:");
1785 xlcredits[3] = _("Special thanks to:");
1786 xlcredits[4] = _("The Free Software Foundation");
1787 xlcredits[5] = _("For ncurses:");
1788 xlcredits[6] = _("and anyone else we forgot...");
1789 xlcredits[7] = _("Thank you for using nano!\n");
1790
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001791 curs_set(0);
1792 nodelay(edit, TRUE);
1793 blank_bottombars();
1794 mvwaddstr(topwin, 0, 0, hblank);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001795 blank_edit();
1796 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001797 wrefresh(bottomwin);
1798 wrefresh(topwin);
1799
1800 while (wgetch(edit) == ERR) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001801 for (k = 0; k <= 1; k++) {
1802 blank_edit();
Chris Allegretta598106e2002-01-19 01:59:37 +00001803 for (i = editwinrows / 2 - 1; i >= (editwinrows / 2 - 1 - j);
1804 i--) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001805 mvwaddstr(edit, i * 2 - k, 0, hblank);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001806
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001807 if (place - (editwinrows / 2 - 1 - i) < CREDIT_LEN) {
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001808 what = credits[place - (editwinrows / 2 - 1 - i)];
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00001809
1810 /* God I've missed hacking. If what is exactly
1811 1 char long, it's a sentinel for a translated
1812 string, so use that instead. This means no
1813 thanking people with 1 character long names ;-) */
1814 if (strlen(what) == 1)
1815 what = xlcredits[atoi(what)];
1816 } else
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001817 what = "";
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001818
Chris Allegretta17dcb722001-01-20 21:40:07 +00001819 start_x = COLS / 2 - strlen(what) / 2 - 1;
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00001820 mvwaddstr(edit, i * 2 - k, start_x, what);
1821 }
1822 usleep(700000);
1823 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001824 }
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001825 if (j < editwinrows / 2 - 1)
1826 j++;
1827
1828 place++;
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001829
1830 if (place >= CREDIT_LEN + editwinrows / 2)
1831 break;
1832 }
1833
1834 nodelay(edit, FALSE);
1835 curs_set(1);
1836 display_main_list();
1837 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00001838}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00001839#endif