blob: c45441689bf3327501e1ad905b0feaf56c67ece6 [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * nano.c *
4 * *
5 * Copyright (C) 1999 Chris Allegretta *
6 * 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 *
8 * the Free Software Foundation; either version 1, or (at your option) *
9 * 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
22#include <stdio.h>
23#include <stdlib.h>
24#include <stdarg.h>
25#include <signal.h>
26#include <unistd.h>
27#include <string.h>
28#include <fcntl.h>
29#include <sys/stat.h>
30#include <sys/ioctl.h>
31#include <sys/param.h>
Chris Allegretta27eb13f2000-11-05 16:52:21 +000032#include <sys/types.h>
33#include <sys/wait.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000034#include <errno.h>
35#include <ctype.h>
36#include <locale.h>
37#include <limits.h>
Adam Rogoyski77f36de2000-06-07 03:56:54 +000038#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000039
40#include "config.h"
41#include "proto.h"
42#include "nano.h"
43
44#ifndef NANO_SMALL
45#include <libintl.h>
46#define _(string) gettext(string)
47#else
48#define _(string) (string)
49#endif
50
51#ifdef HAVE_TERMIOS_H
52#include <termios.h>
53#endif
54
55#ifdef HAVE_TERMIO_H
56#include <termio.h>
57#endif
58
59#ifdef HAVE_GETOPT_H
60#include <getopt.h>
61#endif
62
63/* Former globals, now static */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000064int fill = 0; /* Fill - where to wrap lines, basically */
Rocco Corsiaf5c3022001-01-12 07:51:05 +000065
66#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000067static char *alt_speller; /* Alternative spell command */
Rocco Corsiaf5c3022001-01-12 07:51:05 +000068#endif
69
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000070struct termios oldterm; /* The user's original term settings */
Chris Allegretta18f8be02000-09-04 03:20:38 +000071static struct sigaction act; /* For all out fun signal handlers */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000072
Rocco Corsiaf5c3022001-01-12 07:51:05 +000073#ifndef DISABLE_HELP
Chris Allegretta65121632000-12-18 07:05:27 +000074static char *help_text_init = ""; /* Initial message, not including shortcuts */
75#endif
76
Chris Allegretta27eb13f2000-11-05 16:52:21 +000077char *last_search = NULL; /* Last string we searched for */
78char *last_replace = NULL; /* Last replacement string */
79int search_last_line; /* Is this the last search line? */
80
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000081/* What we do when we're all set to exit */
82RETSIGTYPE finish(int sigage)
83{
Chris Allegrettac08f50d2001-01-06 18:12:43 +000084
85 keypad(edit, TRUE);
86 keypad(bottomwin, TRUE);
87
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000088 if (!ISSET(NO_HELP)) {
89 mvwaddstr(bottomwin, 1, 0, hblank);
90 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000091 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000092 mvwaddstr(bottomwin, 0, 0, hblank);
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +000093
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000094 wrefresh(bottomwin);
95 endwin();
96
97 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +000098 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000099
100 exit(sigage);
101}
102
103/* Die (gracefully?) */
104void die(char *msg, ...)
105{
106 va_list ap;
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000107 char *name;
108 int i;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000109
110 va_start(ap, msg);
111 vfprintf(stderr, msg, ap);
112 va_end(ap);
113
114 /* if we can't save we have REAL bad problems,
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000115 * but we might as well TRY. */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000116 if (filename[0] == '\0') {
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000117 name = "nano.save";
118 i = write_file(name, 1);
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000119 } else {
Chris Allegrettae7a58932000-12-02 02:36:22 +0000120
121 char *buf = nmalloc(strlen(filename) + 6);
122 strcpy(buf, filename);
123 strcat(buf, ".save");
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000124 i = write_file(buf, 1);
125 name = buf;
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000126 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000127 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000128 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000129
130 clear();
131 refresh();
132 resetty();
133 endwin();
134
135 fprintf(stderr, msg);
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000136 if (i != -1)
137 fprintf(stderr, _("\nBuffer written to %s\n"), name);
138 else
Chris Allegretta9756d622000-12-03 03:06:45 +0000139 fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000140
141 exit(1); /* We have a problem: exit w/ errorlevel(1) */
142}
143
Chris Allegrettae61e8302001-01-14 05:18:27 +0000144/* Die with an error message that the screen was too small if, well, the
145 screen is too small */
146void die_too_small(void)
147{
148 char *too_small_msg = _("Window size is too small for Nano...");
149
150 die(too_small_msg);
151
152}
153
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000154void print_view_warning(void)
155{
156 statusbar(_("Key illegal in VIEW mode"));
157}
158
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000159void clear_filename(void)
160{
161 if (filename != NULL)
162 free(filename);
163 filename = nmalloc(1);
164 filename[0] = 0;
165}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000166
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000167/* Initialize global variables - no better way for now */
168void global_init(void)
169{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000170 current_x = 0;
171 current_y = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000172
173 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
174 die_too_small();
175
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000176 fileage = NULL;
177 cutbuffer = NULL;
178 current = NULL;
179 edittop = NULL;
180 editbot = NULL;
181 totlines = 0;
182 placewewant = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000183
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000184 if (!fill)
Chris Allegrettae61e8302001-01-14 05:18:27 +0000185 fill = COLS - CHARS_FROM_EOL;
186
187 if (fill < MIN_FILL_LENGTH)
188 die_too_small();
189
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000190 hblank = nmalloc(COLS + 1);
Chris Allegretta0a06e072001-01-23 02:35:04 +0000191 memset(hblank, ' ', COLS);
192 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000193}
194
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000195#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000196void init_help_msg(void)
197{
198
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000199 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000200 _(" nano help text\n\n "
201 "The nano editor is designed to emulate the functionality and "
202 "ease-of-use of the UW Pico text editor. There are four main "
203 "sections of the editor: The top line shows the program "
204 "version, the current filename being edited, and whether "
205 "or not the file has been modified. Next is the main editor "
206 "window showing the file being edited. The status line is "
207 "the third line from the bottom and shows important messages. "
208 "The bottom two lines show the most commonly used shortcuts "
209 "in the editor.\n\n "
210 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000211 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000212 "with the Control (Ctrl) key. Escape-key sequences are notated "
213 "with the Meta (M) symbol and can be entered using either the "
214 "Esc, Alt or Meta key depending on your keyboard setup. The "
215 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000216 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000217
218}
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000219#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000220
221/* Make a copy of a node to a pointer (space will be malloc()ed) */
222filestruct *copy_node(filestruct * src)
223{
224 filestruct *dst;
225
226 dst = nmalloc(sizeof(filestruct));
227 dst->data = nmalloc(strlen(src->data) + 1);
228
229 dst->next = src->next;
230 dst->prev = src->prev;
231
232 strcpy(dst->data, src->data);
233 dst->lineno = src->lineno;
234
235 return dst;
236}
237
238/* Unlink a node from the rest of the struct */
239void unlink_node(filestruct * fileptr)
240{
241 if (fileptr->prev != NULL)
242 fileptr->prev->next = fileptr->next;
243
244 if (fileptr->next != NULL)
245 fileptr->next->prev = fileptr->prev;
246}
247
248void delete_node(filestruct * fileptr)
249{
Chris Allegretta17dcb722001-01-20 21:40:07 +0000250 if (fileptr == NULL)
251 return;
252
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000253 if (fileptr->data != NULL)
Chris Allegretta17dcb722001-01-20 21:40:07 +0000254 free(fileptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000255 free(fileptr);
256}
257
258/* Okay, now let's duplicate a whole struct! */
259filestruct *copy_filestruct(filestruct * src)
260{
261 filestruct *dst, *tmp, *head, *prev;
262
263 head = copy_node(src);
264 dst = head; /* Else we barf on copying just one line */
265 head->prev = NULL;
266 tmp = src->next;
267 prev = head;
268
269 while (tmp != NULL) {
270 dst = copy_node(tmp);
271 dst->prev = prev;
272 prev->next = dst;
273
274 prev = dst;
275 tmp = tmp->next;
276 }
277
278 dst->next = NULL;
279 return head;
280}
281
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000282int free_filestruct(filestruct * src)
283{
284 filestruct *fileptr = src;
285
286 if (src == NULL)
287 return 0;
288
289 while (fileptr->next != NULL) {
290 fileptr = fileptr->next;
Chris Allegretta17dcb722001-01-20 21:40:07 +0000291 delete_node(fileptr->prev);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000292
293#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000294 fprintf(stderr, _("delete_node(): free'd a node, YAY!\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000295#endif
296 }
Chris Allegretta17dcb722001-01-20 21:40:07 +0000297 delete_node(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000298#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000299 fprintf(stderr, _("delete_node(): free'd last node.\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000300#endif
301
302 return 1;
303}
304
305int renumber_all(void)
306{
307 filestruct *temp;
308 long i = 1;
309
310 for (temp = fileage; temp != NULL; temp = temp->next) {
311 temp->lineno = i++;
312 }
313
314 return 0;
315}
316
317int renumber(filestruct * fileptr)
318{
319 filestruct *temp;
320
321 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
322 renumber_all();
323 return 0;
324 }
325 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000326 if (temp->prev != NULL)
327 temp->lineno = temp->prev->lineno + 1;
328 else
329 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000330 }
331
332 return 0;
333}
334
335/* Fix the memory allocation for a string */
336void align(char **strp)
337{
338 /* There was a serious bug here: the new address was never
339 stored anywhere... */
340
341 *strp = nrealloc(*strp, strlen(*strp) + 1);
342}
343
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000344/* Null a string at a certain index and align it */
345void null_at(char *data, int index)
346{
347 data[index] = 0;
348 align(&data);
349}
350
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000351void usage(void)
352{
353#ifdef HAVE_GETOPT_LONG
354 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
355 printf(_("Option Long option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000356 printf(_
Chris Allegrettae9a2d032001-01-21 16:08:21 +0000357 (" -T [num] --tabsize=[num] Set width of a tab to num\n"));
Chris Allegretta805c26d2000-09-06 13:39:17 +0000358#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000359 printf(_
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000360 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000361#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000362 printf
363 (_
364 (" -V --version Print version information and exit\n"));
365 printf(_
366 (" -c --const Constantly show cursor position\n"));
367 printf(_
368 (" -h --help Show this message\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000369 printf(_
370 (" -i --autoindent Automatically indent new lines\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000371#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000372 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000373 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000374#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000375 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000376 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000377#ifndef NANO_SMALL
378#ifdef NCURSES_MOUSE_VERSION
379 printf(_(" -m --mouse Enable mouse\n"));
380#endif
381#endif
Chris Allegrettad55655f2000-12-27 03:36:47 +0000382 printf(_
383 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000384 printf
385 (_
386 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000387#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000388 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000389 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000390#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000391 printf(_
392 (" -t --tempfile Auto save on exit, don't prompt\n"));
393 printf(_
394 (" -v --view View (read only) mode\n"));
395 printf(_
396 (" -w --nowrap Don't wrap long lines\n"));
397 printf(_
398 (" -x --nohelp Don't show help window\n"));
399 printf(_
400 (" -z --suspend Enable suspend\n"));
401 printf(_
402 (" +LINE Start at line number LINE\n"));
403#else
404 printf(_("Usage: nano [option] +LINE <file>\n\n"));
405 printf(_("Option Meaning\n"));
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000406 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000407 printf(_(" -R Use regular expressions for search\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000408 printf(_(" -V Print version information and exit\n"));
409 printf(_(" -c Constantly show cursor position\n"));
410 printf(_(" -h Show this message\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000411 printf(_(" -i Automatically indent new lines\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000412#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +0000413 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000414#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000415 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000416 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000417#ifndef NANO_SMALL
418#ifdef NCURSES_MOUSE_VERSION
419 printf(_(" -m Enable mouse\n"));
420#endif
421#endif
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000422 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000423 printf(_(" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000424#ifndef DISABLE_SPELLER
Chris Allegrettad55655f2000-12-27 03:36:47 +0000425 printf(_(" -s [prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000426#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000427 printf(_(" -t Auto save on exit, don't prompt\n"));
428 printf(_(" -v View (read only) mode\n"));
429 printf(_(" -w Don't wrap long lines\n"));
430 printf(_(" -x Don't show help window\n"));
431 printf(_(" -z Enable suspend\n"));
432 printf(_(" +LINE Start at line number LINE\n"));
433#endif
434 exit(0);
435}
436
437void version(void)
438{
439 printf(_(" nano version %s by Chris Allegretta (compiled %s, %s)\n"),
440 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000441 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000442 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000443 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000444
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000445#ifdef NANO_EXTRA
446 printf(" --enable-extra");
447#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000448
449#ifdef NANO_SMALL
450 printf(" --enable-tiny");
451#else
452 #ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000453 printf(" --disable-browser");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000454 #endif
455 #ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000456 printf(" --disable-tabcomp");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000457 #endif
458 #ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000459 printf(" --disable-justify");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000460 #endif
461 #ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000462 printf(" --disable-speller");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000463 #endif
464 #ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000465 printf(" --disable-help");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000466 #endif
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000467#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000468
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000469#ifdef USE_SLANG
470 printf(" --with-slang");
471#endif
472 printf("\n");
473
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000474}
475
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000476filestruct *make_new_node(filestruct * prevnode)
477{
478 filestruct *newnode;
479
480 newnode = nmalloc(sizeof(filestruct));
481 newnode->data = NULL;
482
483 newnode->prev = prevnode;
484 newnode->next = NULL;
485
486 if (prevnode != NULL)
487 newnode->lineno = prevnode->lineno + 1;
488
489 return newnode;
490}
491
Chris Allegretta7975ed82000-07-28 00:58:35 +0000492/* Splice a node into an existing filestruct */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000493void splice_node(filestruct * begin, filestruct * new, filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000494{
495 new->next = end;
496 new->prev = begin;
497 begin->next = new;
498 if (end != NULL)
499 end->prev = new;
500}
501
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000502int do_mark()
503{
504#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000505 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000506#else
507 if (!ISSET(MARK_ISSET)) {
508 statusbar(_("Mark Set"));
509 SET(MARK_ISSET);
510 mark_beginbuf = current;
511 mark_beginx = current_x;
512 } else {
513 statusbar(_("Mark UNset"));
514 UNSET(MARK_ISSET);
515 mark_beginbuf = NULL;
516 mark_beginx = 0;
517
518 edit_refresh();
519 }
520#endif
521 return 1;
522}
523
524int no_help(void)
525{
526 if ISSET
527 (NO_HELP)
528 return 2;
529 else
530 return 0;
531}
532
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000533#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000534void nano_disabled_msg(void)
535{
536 statusbar("Sorry, support for this function has been disabled");
537}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000538#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000539
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000540/* The user typed a printable character; add it to the edit buffer */
541void do_char(char ch)
542{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000543 /* magic-line: when a character is inserted on the current magic line,
544 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000545 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000546 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000547 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000548 }
549
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000550 /* More dangerousness fun =) */
551 current->data = nrealloc(current->data, strlen(current->data) + 2);
552 memmove(&current->data[current_x + 1],
553 &current->data[current_x],
554 strlen(current->data) - current_x + 1);
555 current->data[current_x] = ch;
556 do_right();
557
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000558 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000559 check_wrap(current, ch);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000560 set_modified();
561 check_statblank();
562 UNSET(KEEP_CUTBUFFER);
563 totsize++;
564
565}
566
567/* Someone hits return *gasp!* */
568int do_enter(filestruct * inptr)
569{
570 filestruct *new;
571 char *tmp, *spc;
572 int extra = 0;
573
574 new = make_new_node(inptr);
575 tmp = &current->data[current_x];
576 current_x = 0;
577
578 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
579 if (ISSET(AUTOINDENT)) {
580 spc = current->data;
581 if (spc) {
582 while ((*spc == ' ') || (*spc == '\t')) {
583 extra++;
584 spc++;
585 current_x++;
586 }
587 new->data = nmalloc(strlen(tmp) + extra + 1);
588 strncpy(new->data, current->data, extra);
589 strcpy(&new->data[extra], tmp);
590 }
591 } else {
592 new->data = nmalloc(strlen(tmp) + 1);
593 strcpy(new->data, tmp);
594 }
595 *tmp = 0;
596
Chris Allegrettada721be2000-07-31 01:26:42 +0000597 if (inptr->next == NULL) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000598 filebot = new;
599 editbot = new;
600 }
Chris Allegretta7975ed82000-07-28 00:58:35 +0000601 splice_node(inptr, new, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000602
603 totsize++;
604 renumber(current);
605 current = new;
606 align(&current->data);
607
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000608 /* The logic here is as follows:
609 * -> If we are at the bottom of the buffer, we want to recenter
610 * (read: rebuild) the screen and forcably move the cursor.
611 * -> otherwise, we want simply to redraw the screen and update
612 * where we think the cursor is.
613 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000614 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000615 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000616 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000617 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000618 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000619 edit_refresh();
620 update_cursor();
621 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000622
623 totlines++;
624 set_modified();
625
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000626 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000627 return 1;
628}
629
630int do_enter_void(void)
631{
632 return do_enter(current);
633}
634
635void do_next_word(void)
636{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000637 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000638 int i;
639
640 if (current == NULL)
641 return;
642
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000643 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000644 i = current_x;
645 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
646 if (fileptr == current) {
647 while (isalnum((int) fileptr->data[i])
648 && fileptr->data[i] != 0)
649 i++;
650
651 if (fileptr->data[i] == 0) {
652 i = 0;
653 continue;
654 }
655 }
656 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
657 i++;
658
659 if (fileptr->data[i] != 0)
660 break;
661
662 i = 0;
663 }
664 if (fileptr == NULL)
665 current = filebot;
666 else
667 current = fileptr;
668
669 current_x = i;
670 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000671
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000672 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000673 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000674 else {
675 /* If we've jumped lines, refresh the old line. We can't just use
676 * current->prev here, because we may have skipped over some blank
677 * lines, in which case the previous line is the wrong one.
678 */
679 if (current != old)
680 update_line(old, 0);
681
682 update_line(current, current_x);
683 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000684
685}
686
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000687void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000688{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000689 int i = 0; /* Index into ->data for line. */
690 int i_tabs = 0; /* Screen position of ->data[i]. */
691 int last_word_end = -1; /* Location of end of last word found. */
692 int current_word_start = -1; /* Location of start of current word. */
693 int current_word_start_t = -1; /* Location of start of current word screen position. */
694 int current_word_end = -1; /* Location of end of current word */
695 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000696 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000697
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000698 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000699 int right = 0;
700 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000701
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000702 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000703
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000704 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000705 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000706 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000707
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000708 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000709 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000710
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000711 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000712 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000713 i++;
714 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000715 if (inptr->data[i] < 32)
716 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000717 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000718
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000719 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000720 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000721 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000722 } else {
723 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000724 current_word_end_t = i_tabs - 1;
725 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000726 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000727
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000728 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000729 if (i_tabs % tabsize != 0);
730 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000731 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000732
Adam Rogoyski09f97962000-06-20 02:50:33 +0000733 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000734 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000735 }
736
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000737 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000738 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000739 * a) one word takes up the whole line with no starting spaces.
740 * - do nothing and return.
741 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000742 * - word starts new line.
743 * - keep white space on original line up to the cursor.
744 * *) cursor is after word at wrap point
745 * - either it's all white space after word, and this routine isn't called.
746 * - or we are actually in case 2 (2 words).
747 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000748 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000749 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000750 * - white space at end of original line is cleared, unless
751 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000752 * b) cursor is at the word at the wrap point.
753 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000754 * 1. pressed a space and at first character of wrap point word.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000755 * - white space on original line is kept to where cursor was.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000756 * 2. pressed non space (or space elsewhere).
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000757 * - white space at end of original line is cleared.
758 * c) cursor is past the word at the wrap point.
759 * - word at wrap point starts a new line.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000760 * - white space at end of original line is cleared
761 */
762
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000763 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000764
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000765 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000766 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000767 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000768 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000769 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000770 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000771 i++;
772 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000773 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000774 current_word_end = i;
775 break;
776 }
777 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000778
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000779 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000780 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000781 return;
782 }
783 if (current_x >= last_word_end) {
784 right = (current_x - current_word_start) + 1;
785 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000786 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000787 }
788
789 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
790 strcpy(temp->data, &inptr->data[current_word_start]);
791 inptr->data = nrealloc(inptr->data, last_word_end + 2);
792 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000793 } else
794 /* Category 1b: one word on the line and word not taking up whole line
795 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000796 if (last_word_end == -1) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000797 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
798 strcpy(temp->data, &inptr->data[current_word_start]);
799
800 /* Inside word, remove it from original, and move cursor to right spot. */
801 if (current_x >= current_word_start) {
802 right = current_x - current_word_start;
803 current_x = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000804 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000805 }
806
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000807 null_at(inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000808
809 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
810 mark_beginbuf = temp;
811 mark_beginx = 0;
812 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000813 }
814
815 /* Category 2: two or more words on the line. */
816 else {
817
818 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000819 if (current_x < current_word_start) {
820 temp->data =
821 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
822 strcpy(temp->data, &inptr->data[current_word_start]);
823
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000824 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000825 i = current_word_start - 1;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000826 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000827 i--;
828 assert(i >= 0);
829 }
830 } else if (current_x <= last_word_end)
831 i = last_word_end - 1;
832 else
833 i = current_x;
834
835 inptr->data = nrealloc(inptr->data, i + 2);
836 inptr->data[i + 1] = 0;
837 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000838
839
840 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000841 else if ((current_x >= current_word_start)
842 && (current_x <= (current_word_end + 1))) {
843 temp->data =
844 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000845 strcpy(temp->data, &inptr->data[current_word_start]);
846
847 down = 1;
848
849 right = current_x - current_word_start;
850 i = current_word_start - 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000851 if (isspace((int) input_char)
852 && (current_x == current_word_start)) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000853 current_x = current_word_start;
854
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000855 null_at(inptr->data, current_word_start);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000856 } else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000857
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000858 while (isspace((int) inptr->data[i])) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000859 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000860 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000861 }
862 inptr->data = nrealloc(inptr->data, i + 2);
863 inptr->data[i + 1] = 0;
864 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000865 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000866
867
868 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000869 else {
870 temp->data =
871 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000872 strcpy(temp->data, &inptr->data[current_word_start]);
873
874 down = 1;
875 right = current_x - current_word_start;
876
877 current_x = current_word_start;
878 i = current_word_start - 1;
879
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000880 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000881 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000882 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000883 inptr->data = nrealloc(inptr->data, i + 2);
884 inptr->data[i + 1] = 0;
885 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000886 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000887 }
888
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000889 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000890 if (ISSET(SAMELINEWRAP) && inptr->next) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000891 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
892 char *p =
893 nmalloc(strlen(temp->data) + strlen(inptr->next->data) + 2);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000894 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000895
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000896 strcpy(p, temp->data);
897 strcat(p, " ");
898 strcat(p, inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000899
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000900 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000901 inptr->next->data = p;
902
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000903 free(temp->data);
904 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000905
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000906 current_x = old_x;
907 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000908 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000909 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000910 else {
911 temp->prev = inptr;
912 temp->next = inptr->next;
913
914 if (inptr->next)
915 inptr->next->prev = temp;
916 inptr->next = temp;
917
918 if (!temp->next)
919 filebot = temp;
920
921 SET(SAMELINEWRAP);
922 }
923
924
925 totlines++;
Robert Siemborskia417ddc2000-07-24 23:18:48 +0000926 /* Everything about it makes me want this line here but it causes
927 * totsize to be high by one for some reason. Sigh. (Rob) */
928 /* totsize++; */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000929
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000930 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +0000931 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000932
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000933
934 /* Move the cursor to the new line if appropriate. */
935 if (down) {
936 do_right();
937 }
938
939 /* Move the cursor to the correct spot in the line if appropriate. */
940 while (right--) {
941 do_right();
942 }
943
Chris Allegretta234a34d2000-07-29 04:33:38 +0000944 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000945 reset_cursor();
946 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000947}
948
949/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000950void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000951{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000952 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000953#ifdef DEBUG
954 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
955 inptr->data);
956#endif
957
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000958 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000959 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000960 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000961 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000962
963 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000964 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000965
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000966 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +0000967 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000968
Adam Rogoyski09f97962000-06-20 02:50:33 +0000969 if (!inptr->data[i])
970 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000971
Adam Rogoyski09f97962000-06-20 02:50:33 +0000972 /* String must be at least 1 character long. */
973 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000974 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +0000975 if (!char_found)
976 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000977 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000978 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000979 } else
980 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000981 }
Adam Rogoyski09f97962000-06-20 02:50:33 +0000982
983 if (char_found == 2)
984 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000985 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000986}
987
988/* Stuff we do when we abort from programs and want to clean up the
989 * screen. This doesnt do much right now.
990 */
991void do_early_abort(void)
992{
993 blank_statusbar_refresh();
994}
995
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000996int do_backspace(void)
997{
998 filestruct *previous, *tmp;
999
1000 if (current_x != 0) {
1001 /* Let's get dangerous */
1002 memmove(&current->data[current_x - 1], &current->data[current_x],
1003 strlen(current->data) - current_x + 1);
1004#ifdef DEBUG
1005 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1006#endif
1007 align(&current->data);
1008 do_left();
1009 } else {
1010 if (current == fileage)
1011 return 0; /* Can't delete past top of file */
1012
1013 previous = current->prev;
1014 current_x = strlen(previous->data);
1015 previous->data = nrealloc(previous->data,
1016 strlen(previous->data) +
1017 strlen(current->data) + 1);
1018 strcat(previous->data, current->data);
1019
1020 tmp = current;
1021 unlink_node(current);
1022 delete_node(current);
1023 if (current == edittop) {
1024 if (previous->next)
1025 current = previous->next;
1026 else
1027 current = previous;
Chris Allegrettada721be2000-07-31 01:26:42 +00001028 page_up_center();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001029 } else {
1030 if (previous->next)
1031 current = previous->next;
1032 else
1033 current = previous;
1034 update_line(current, current_x);
1035 }
1036
1037 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001038 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001039 filebot = current;
1040 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001041
1042 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001043 line we're on now is NOT blank. if it is blank we
1044 can just use IT for the magic line. This is how Pico
1045 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001046 if (strcmp(current->data, "")) {
1047 new_magicline();
1048 fix_editbot();
1049 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001050 }
1051
1052 current = previous;
1053 renumber(current);
1054 previous_line();
1055 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001056#ifdef DEBUG
1057 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1058#endif
1059
1060 }
1061
1062 totsize--;
1063 set_modified();
1064 UNSET(KEEP_CUTBUFFER);
1065 edit_refresh();
1066 return 1;
1067}
1068
1069int do_delete(void)
1070{
1071 filestruct *foo;
1072
1073 if (current_x != strlen(current->data)) {
1074 /* Let's get dangerous */
1075 memmove(&current->data[current_x], &current->data[current_x + 1],
1076 strlen(current->data) - current_x);
1077
1078 align(&current->data);
1079
1080 } else if (current->next != NULL) {
1081 current->data = nrealloc(current->data,
1082 strlen(current->data) +
1083 strlen(current->next->data) + 1);
1084 strcat(current->data, current->next->data);
1085
1086 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001087 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001088 filebot = current;
1089 editbot = current;
1090 }
1091
1092 unlink_node(foo);
1093 delete_node(foo);
1094 update_line(current, current_x);
1095
Chris Allegretta28a0f892000-07-05 22:47:54 +00001096 /* Please see the comment in do_basckspace if you don't understand
1097 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001098 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001099 new_magicline();
1100 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001101 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001102 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001103 renumber(current);
1104 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001105 } else
1106 return 0;
1107
1108 totsize--;
1109 set_modified();
1110 UNSET(KEEP_CUTBUFFER);
1111 edit_refresh();
1112 return 1;
1113}
1114
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001115void wrap_reset(void)
1116{
1117 UNSET(SAMELINEWRAP);
1118}
1119
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001120#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001121
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001122int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001123{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001124 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001125 filestruct *begin;
1126 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001127
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001128 /* save where we are */
1129 begin = current;
1130 beginx = current_x + 1;
1131
1132 /* save the current search/replace strings */
1133 search_init_globals();
1134 save_search = mallocstrcpy(save_search, last_search);
1135 save_replace = mallocstrcpy(save_replace, last_replace);
1136
1137 /* set search/replace strings to mis-spelt word */
1138 prevanswer = mallocstrcpy(prevanswer, word);
1139 last_search = mallocstrcpy(last_search, word);
1140 last_replace = mallocstrcpy(last_replace, word);
1141
1142 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001143 current = fileage;
1144 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001145
1146 search_last_line = FALSE;
1147
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001148 edit_update(fileage, TOP);
1149
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001150 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001151 if (findnextstr(TRUE, fileage, beginx_top, prevanswer) != NULL)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001152 {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001153 do_replace_highlight(TRUE, prevanswer);
1154
1155 /* allow replace word to be corrected */
1156 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1157 _("Edit a replacement"));
1158
1159 do_replace_highlight(FALSE, prevanswer);
1160
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001161 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001162 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001163 current_x = beginx_top;
1164
1165 search_last_line = FALSE;
1166
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001167 j = i;
1168 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001169 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001170
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001171 /* restore the search/replace strings */
1172 last_search = mallocstrcpy(last_search, save_search);
1173 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001174
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001175 /* restore where we were */
1176 current = begin;
1177 current_x = beginx - 1;
1178
1179 edit_update(current, CENTER);
1180
1181 if (i == -1)
1182 return FALSE;
1183
1184 return TRUE;
1185}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001186
1187/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001188int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001189{
Chris Allegretta271e9722000-11-10 18:15:43 +00001190 char *read_buff, *read_buff_ptr, *read_buff_word;
1191 long pipe_buff_size;
1192 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001193 int spell_status;
1194 pid_t pid_spell;
1195 ssize_t bytesread;
1196
Chris Allegretta271e9722000-11-10 18:15:43 +00001197 /* Create a pipe to spell program */
1198
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001199 if (pipe(in_fd) == -1)
1200 return FALSE;
1201
Chris Allegretta271e9722000-11-10 18:15:43 +00001202 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001203
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001204 if ( (pid_spell = fork()) == 0) {
1205
1206 /* Child continues, (i.e. future spell process) */
1207
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001208 close(in_fd[0]);
1209
Chris Allegretta271e9722000-11-10 18:15:43 +00001210 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001211
Chris Allegretta271e9722000-11-10 18:15:43 +00001212 if ( (tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
1213
1214 close(in_fd[1]);
1215 exit(1);
1216 }
1217
1218 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1219
1220 close(tempfile_fd);
1221 close(in_fd[1]);
1222 exit(1);
1223 }
1224 close(tempfile_fd);
1225
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001226
Chris Allegretta271e9722000-11-10 18:15:43 +00001227 /* send spell's standard out to the pipe */
1228
1229 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1230
1231 close(in_fd[1]);
1232 exit(1);
1233 }
1234 close(in_fd[1]);
1235
1236 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001237 execlp("spell", "spell", NULL);
1238
Chris Allegretta271e9722000-11-10 18:15:43 +00001239 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001240
Chris Allegretta271e9722000-11-10 18:15:43 +00001241 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001242 }
1243
1244 /* Parent continues here */
1245
Chris Allegretta271e9722000-11-10 18:15:43 +00001246 close(in_fd[1]);
1247
1248 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001249
1250 if (pid_spell < 0) {
1251
Chris Allegretta271e9722000-11-10 18:15:43 +00001252 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001253 return FALSE;
1254 }
1255
Chris Allegretta271e9722000-11-10 18:15:43 +00001256 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001257
Chris Allegretta271e9722000-11-10 18:15:43 +00001258 if ( (pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001259
Chris Allegretta271e9722000-11-10 18:15:43 +00001260 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001261 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001262 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001263
Chris Allegretta271e9722000-11-10 18:15:43 +00001264 read_buff = nmalloc( pipe_buff_size + 1 );
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001265
Chris Allegretta271e9722000-11-10 18:15:43 +00001266 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001267
Chris Allegretta271e9722000-11-10 18:15:43 +00001268 while ( (bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001269
Chris Allegretta271e9722000-11-10 18:15:43 +00001270 read_buff[bytesread] = (char) NULL;
1271 read_buff_word = read_buff_ptr = read_buff;
1272
1273 while (*read_buff_ptr != (char) NULL) {
1274
1275 /* Windows version may need to process additional char '\r' */
1276
1277 /* Possible problem here if last word not followed by '\n' */
1278
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001279 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001280 *read_buff_ptr = (char) NULL;
1281 if (!do_int_spell_fix(read_buff_word)) {
1282
1283 close(in_fd[0]);
1284 free(read_buff);
1285 replace_abort();
1286
1287 return TRUE;
1288 }
1289 read_buff_word = read_buff_ptr;
1290 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001291 }
1292
1293 read_buff_ptr++;
1294 }
1295 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001296
1297 close(in_fd[0]);
1298 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001299 replace_abort();
1300
Chris Allegretta271e9722000-11-10 18:15:43 +00001301 /* Process end of spell process */
1302
1303 wait(&spell_status);
1304 if (WIFEXITED(spell_status)) {
1305 if (WEXITSTATUS(spell_status) != 0)
1306 return FALSE;
1307 }
1308 else
1309 return FALSE;
1310
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001311 return TRUE;
1312}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001313
1314/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001315int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001316{
Chris Allegretta271e9722000-11-10 18:15:43 +00001317 int alt_spell_status;
1318 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001319 char *ptr;
1320 static int arglen = 3;
1321 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001322
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001323 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001324
Chris Allegrettae434b452001-01-27 19:25:00 +00001325 /* Set up an argument list to pass the execvp function */
1326 if (spellargs == NULL) {
1327 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001328
Chris Allegrettae434b452001-01-27 19:25:00 +00001329 spellargs[0] = strtok(alt_speller, " ");
1330 while ((ptr = strtok(NULL, " ")) != NULL) {
1331 arglen++;
1332 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1333 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001334 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001335 spellargs[arglen - 1] = NULL;
1336 }
1337 spellargs[arglen - 2] = file_name;
1338
1339 /* Start a new process for the alternate speller */
1340 if ( (pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001341
Chris Allegretta271e9722000-11-10 18:15:43 +00001342 /* Start alternate spell program, we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001343 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001344
1345 /* Should not be reached, if alternate speller is found!!! */
1346
1347 exit(1);
1348 }
1349
1350 /* Could not fork?? */
1351
1352 if (pid_spell < 0)
1353 return FALSE;
1354
1355 /* Wait for alternate speller to complete */
1356
1357 wait(&alt_spell_status);
1358 if (WIFEXITED(alt_spell_status)) {
1359 if (WEXITSTATUS(alt_spell_status) != 0)
1360 return FALSE;
1361 }
1362 else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001363 return FALSE;
1364
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001365 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001366 free_filestruct(fileage);
1367 global_init();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001368 open_file(file_name, 0, 1);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001369 edit_update(fileage, CENTER);
Chris Allegretta271e9722000-11-10 18:15:43 +00001370 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001371 set_modified();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001372
1373 return TRUE;
1374}
1375#endif
1376
1377int do_spell(void)
1378{
1379
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001380#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001381 nano_disabled_msg();
1382 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001383#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001384 char *temp;
1385 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001386
Chris Allegretta271e9722000-11-10 18:15:43 +00001387 if ((temp = tempnam(0, "nano.")) == NULL) {
1388 statusbar(_("Could not create a temporary filename: %s"),
1389 strerror(errno));
1390 return 0;
1391 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001392
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001393 if (write_file(temp, 1) == -1) {
1394 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001395 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001396 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001397
Chris Allegretta271e9722000-11-10 18:15:43 +00001398 if (alt_speller)
1399 spell_res = do_alt_speller(temp);
1400 else
1401 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001402
Chris Allegretta271e9722000-11-10 18:15:43 +00001403 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001404
1405 if (spell_res)
1406 statusbar(_("Finished checking spelling"));
1407 else
1408 statusbar(_("Spell checking failed"));
1409
1410 return spell_res;
1411
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001412#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001413}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001414
1415int do_exit(void)
1416{
1417 int i;
1418
1419 if (!ISSET(MODIFIED))
1420 finish(0);
1421
Chris Allegretta30885552000-07-14 01:20:12 +00001422 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001423 i = 1;
1424 } else {
1425 i =
1426 do_yesno(0, 0,
1427 _
1428 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1429 }
1430
1431#ifdef DEBUG
1432 dump_buffer(fileage);
1433#endif
1434
1435 if (i == 1) {
Chris Allegrettae1ebaf32001-01-07 05:50:36 +00001436 if (do_writeout(filename, 1) > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001437 finish(0);
1438 } else if (i == 0)
1439 finish(0);
1440 else
1441 statusbar(_("Cancelled"));
1442
1443 display_main_list();
1444 return 1;
1445}
1446
1447#ifndef NANO_SMALL
1448#ifdef NCURSES_MOUSE_VERSION
1449void do_mouse(void)
1450{
1451 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001452 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001453
1454 if (getmouse(&mevent) == ERR)
1455 return;
1456
1457 /* If mouse not in edit window, return (add help selection later). */
1458 if (!wenclose(edit, mevent.y, mevent.x))
1459 return;
1460
1461 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1462 mevent.y -= 2;
1463
1464 /* Selecting where the cursor is sets the mark.
1465 * Selecting beyond the line length with the cursor at the end of the
1466 * line sets the mark as well.
1467 */
1468 if ((mevent.y == current_y) &&
1469 ((mevent.x == current_x) || (current_x == strlen(current->data)
1470 && (mevent.x >
1471 strlen(current->data))))) {
1472 if (ISSET(VIEW_MODE)) {
1473 print_view_warning();
1474 return;
1475 }
1476 do_mark();
1477 } else if (mevent.y > current_y) {
1478 while (mevent.y > current_y) {
1479 if (current->next != NULL)
1480 current = current->next;
1481 else
1482 break;
1483 current_y++;
1484 }
1485 } else if (mevent.y < current_y) {
1486 while (mevent.y < current_y) {
1487 if (current->prev != NULL)
1488 current = current->prev;
1489 else
1490 break;
1491 current_y--;
1492 }
1493 }
1494 current_x = mevent.x;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001495 placewewant = current_x;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001496 while (foo < current_x) {
1497 if (current->data[foo] == NANO_CONTROL_I) {
Chris Allegrettae10debd2000-08-22 01:26:42 +00001498 current_x -= tabsize - (foo % tabsize);
1499 tab_found = 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001500 } else if (current->data[foo] & 0x80);
1501 else if (current->data[foo] < 32)
Chris Allegrettae10debd2000-08-22 01:26:42 +00001502 current_x--;
1503 foo++;
1504 }
1505 /* This is where tab_found comes in. I can't figure out why,
1506 * but without it any line with a tab will place the cursor
1507 * one character behind. Whatever, this fixes it. */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001508 if (tab_found == 1)
Chris Allegrettae10debd2000-08-22 01:26:42 +00001509 current_x++;
1510
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001511 if (current_x > strlen(current->data))
1512 current_x = strlen(current->data);
1513
1514 update_cursor();
1515 edit_refresh();
1516
1517}
1518#endif
1519#endif
1520
1521/* Handler for SIGHUP */
1522RETSIGTYPE handle_hup(int signal)
1523{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001524 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001525}
1526
Chris Allegretta18f8be02000-09-04 03:20:38 +00001527/* What do we do when we catch the suspend signal */
1528RETSIGTYPE do_suspend(int signal)
1529{
1530
1531 act.sa_handler = SIG_DFL;
1532 sigemptyset(&act.sa_mask);
1533 sigaction(SIGTSTP, &act, NULL);
1534
1535 endwin();
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001536 fprintf(stderr, "\n\n\n\n\nUse \"fg\" to return to nano\n");
Chris Allegretta18f8be02000-09-04 03:20:38 +00001537 raise(SIGTSTP);
1538}
1539
1540/* Restore the suspend handler when we come back into the prog */
1541RETSIGTYPE do_cont(int signal)
1542{
1543
1544 act.sa_handler = do_suspend;
1545 sigemptyset(&act.sa_mask);
1546 sigaction(SIGTSTP, &act, NULL);
1547 initscr();
1548 total_refresh();
1549}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001550
1551void handle_sigwinch(int s)
1552{
1553#ifndef NANO_SMALL
1554 char *tty = NULL;
1555 int fd = 0;
1556 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001557 struct winsize win;
1558
1559 tty = ttyname(0);
1560 if (!tty)
1561 return;
1562 fd = open(tty, O_RDWR);
1563 if (fd == -1)
1564 return;
1565 result = ioctl(fd, TIOCGWINSZ, &win);
1566 if (result == -1)
1567 return;
1568
1569
1570 COLS = win.ws_col;
1571 LINES = win.ws_row;
1572
Chris Allegrettae61e8302001-01-14 05:18:27 +00001573 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1574 die_too_small();
1575
1576 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1577 die_too_small();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001578
Chris Allegretta0a06e072001-01-23 02:35:04 +00001579 hblank = nrealloc(hblank, COLS + 1);
1580 memset(hblank, ' ', COLS);
1581 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001582
1583#ifdef HAVE_NCURSES_H
1584 resizeterm(LINES, COLS);
1585#ifdef HAVE_WRESIZE
1586 if (wresize(topwin, 2, COLS) == ERR)
1587 die(_("Cannot resize top win"));
1588 if (mvwin(topwin, 0, 0) == ERR)
1589 die(_("Cannot move top win"));
1590 if (wresize(edit, editwinrows, COLS) == ERR)
1591 die(_("Cannot resize edit win"));
1592 if (mvwin(edit, 2, 0) == ERR)
1593 die(_("Cannot move edit win"));
1594 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1595 die(_("Cannot resize bottom win"));
1596 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1597 die(_("Cannot move bottom win"));
1598#endif /* HAVE_WRESIZE */
1599#endif /* HAVE_NCURSES_H */
1600
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001601 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001602
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001603 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001604 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001605 }
1606 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001607
1608 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001609 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001610 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00001611 edit_refresh();
1612 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001613 total_refresh();
1614#endif
1615}
1616
Chris Allegretta756f2202000-09-01 13:32:47 +00001617void signal_init(void)
1618{
Chris Allegretta756f2202000-09-01 13:32:47 +00001619
1620 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
1621 memset(&act, 0, sizeof(struct sigaction));
1622 act.sa_handler = SIG_IGN;
1623 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00001624
Chris Allegretta18f8be02000-09-04 03:20:38 +00001625 if (!ISSET(SUSPEND)) {
Chris Allegretta756f2202000-09-01 13:32:47 +00001626 sigaction(SIGTSTP, &act, NULL);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001627 } else {
Chris Allegretta18f8be02000-09-04 03:20:38 +00001628 act.sa_handler = do_suspend;
1629 sigaction(SIGTSTP, &act, NULL);
1630
1631 act.sa_handler = do_cont;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001632 sigaction(SIGCONT, &act, NULL);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001633 }
1634
Chris Allegretta756f2202000-09-01 13:32:47 +00001635
1636 /* Trap SIGHUP cuz we want to write the file out. */
1637 act.sa_handler = handle_hup;
1638 sigaction(SIGHUP, &act, NULL);
1639
1640 act.sa_handler = handle_sigwinch;
1641 sigaction(SIGWINCH, &act, NULL);
1642
1643}
1644
Chris Allegretta2a42af12000-09-12 23:02:49 +00001645void window_init(void)
1646{
Chris Allegrettae61e8302001-01-14 05:18:27 +00001647 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1648 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00001649
Chris Allegretta2a42af12000-09-12 23:02:49 +00001650 /* Setup up the main text window */
1651 edit = newwin(editwinrows, COLS, 2, 0);
1652
1653 /* And the other windows */
1654 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001655 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001656
Chris Allegretta155d6202001-01-08 01:50:37 +00001657#ifdef PDCURSES
1658 /* Oops, I guess we need this again.
1659 Moved here so the keypad still works after a Meta-X, for example */
1660 keypad(edit, TRUE);
1661 keypad(bottomwin, TRUE);
1662#endif
1663
Chris Allegretta2a42af12000-09-12 23:02:49 +00001664}
1665
Chris Allegretta756f2202000-09-01 13:32:47 +00001666void mouse_init(void)
1667{
1668#ifndef NANO_SMALL
1669#ifdef NCURSES_MOUSE_VERSION
1670 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001671 keypad_on(edit, 1);
1672
Chris Allegretta756f2202000-09-01 13:32:47 +00001673 mousemask(BUTTON1_RELEASED, NULL);
1674 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00001675
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001676 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00001677 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001678
Chris Allegretta756f2202000-09-01 13:32:47 +00001679#endif
1680#endif
1681
1682}
1683
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001684int do_tab(void)
1685{
1686 do_char('\t');
1687 return 1;
1688}
1689
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001690#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001691int empty_line(const char *data)
1692{
1693 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001694 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001695 return 0;
1696
1697 data++;
1698 }
1699
1700 return 1;
1701}
1702
1703int no_spaces(const char *data)
1704{
1705 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001706 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001707 return 0;
1708
1709 data++;
1710 }
1711
1712 return 1;
1713}
1714
1715void justify_format(char *data)
1716{
1717 int i = 0;
1718 int len = strlen(data);
1719
1720 /* Skip first character regardless and leading whitespace. */
1721 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001722 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001723 break;
1724 }
1725
1726 i++; /* (i) is now at least 2. */
1727
1728 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
1729 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001730 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001731 && (data[i - 2] != '.')) {
1732 memmove(data + i, data + i + 1, len - i);
1733 len--;
1734 i--;
1735 }
1736 }
1737}
1738#endif
1739
1740int do_justify(void)
1741{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001742#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00001743 nano_disabled_msg();
1744 return 1;
1745#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001746 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00001747 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00001748 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001749
1750 if (empty_line(current->data)) {
1751 /* Justify starting at first non-empty line. */
1752 do {
1753 if (!current->next)
1754 return 1;
1755
1756 current = current->next;
1757 current_y++;
1758 }
1759 while (empty_line(current->data));
1760 } else {
1761 /* Search back for the beginning of the paragraph, where
1762 * Paragraph is 1) A line with leading whitespace
1763 * or 2) A line following an empty line.
1764 */
1765 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001766 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001767 break;
1768
1769 current = current->prev;
1770 current_y--;
1771 }
1772
1773 /* First line with leading whitespace may be empty. */
1774 if (empty_line(current->data)) {
1775 if (current->next) {
1776 current = current->next;
1777 current_y++;
1778 } else
1779 return 1;
1780 }
1781 }
1782 initial = current;
1783 initial_y = current_y;
1784
1785 set_modified();
Chris Allegretta9149e612000-11-27 00:23:41 +00001786 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00001787 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00001788 cutbuffer = NULL;
1789
1790 tmptop = current;
1791 tmpjust = copy_node(current);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001792
1793 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00001794 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001795
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001796 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001797 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001798 && current->next->data[0]) {
1799 filestruct *tmpnode = current->next;
1800 int len = strlen(current->data);
1801 int len2 = strlen(current->next->data);
1802
Chris Allegretta9149e612000-11-27 00:23:41 +00001803 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00001804 tmpjust = copy_node(current->next);
1805 add_to_cutbuffer(tmpjust);
1806
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001807 /* Wiping out a newline */
1808 totsize--;
1809
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001810 /* length of both strings plus space between strings and ending \0. */
1811 current->data = nrealloc(current->data, len + len2 + 2);
1812 current->data[len++] = ' ';
1813 current->data[len] = '\0';
1814
1815 strncat(current->data, current->next->data, len2);
1816
1817 unlink_node(tmpnode);
1818 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001819 }
1820
1821 justify_format(current->data);
1822
1823 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001824 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001825
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001826 if ((strlenpt(current->data) > (fill))
1827 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001828 do {
1829 int i = 0;
1830 int len2 = 0;
1831 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001832
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001833 /* Start at fill , unless line isn't that long (but it
1834 * appears at least fill long with tabs.
1835 */
1836 if (slen > fill)
1837 i = fill;
1838 else
1839 i = slen;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001840
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001841 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001842 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001843 ((strlenpt(current->data) - strlen(current->data + i))
1844 <= fill))
1845 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001846 }
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001847
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001848 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001849 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001850
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001851 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001852
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001853 len2 = strlen(current->data + i + 1);
1854 tmpline->data = nmalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001855
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001856 /* Skip the white space in current. */
1857 memcpy(tmpline->data, current->data + i + 1, len2);
1858 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001859
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001860 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001861
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001862 tmpline->prev = current;
1863 tmpline->next = current->next;
1864 if (current->next != NULL)
1865 current->next->prev = tmpline;
1866
1867 current->next = tmpline;
1868 current = tmpline;
1869 slen -= i + 1;
1870 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001871 } while ((strlenpt(current->data) > (fill))
1872 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001873 }
Chris Allegretta9149e612000-11-27 00:23:41 +00001874 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001875
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001876 if (current->next)
1877 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00001878 else
1879 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001880 current_x = 0;
1881 placewewant = 0;
1882
Adam Rogoyski09f97962000-06-20 02:50:33 +00001883 renumber(initial);
1884 totlines = filebot->lineno;
1885
1886 werase(edit);
1887
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001888 if ((current_y < 0) || (current_y >= editwinrows - 1)
1889 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001890 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001891 center_cursor();
1892 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001893 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001894 }
1895
Adam Rogoyski09f97962000-06-20 02:50:33 +00001896 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00001897 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00001898 /* Change the shortcut list to display the unjustify code */
1899 shortcut_init(1);
1900 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00001901 reset_cursor();
1902
Chris Allegretta07798352000-11-27 22:58:23 +00001903 /* Now get a keystroke and see if it's unjustify, if not unget the keytroke
Chris Allegretta9149e612000-11-27 00:23:41 +00001904 and return */
Chris Allegretta4a9c8582000-11-27 22:59:40 +00001905 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY)
Chris Allegretta07798352000-11-27 22:58:23 +00001906 ungetch(kbinput);
Chris Allegretta9149e612000-11-27 00:23:41 +00001907 else {
1908 /* Else restore the justify we just did (ungrateful user!) */
1909 if (tmptop->prev != NULL)
1910 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00001911 else
1912 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00001913 tmpbot->next->prev = tmptop->prev;
1914 current = tmpbot->next;
1915 tmpbot->next = NULL;
1916 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00001917 if (tmptop->prev == NULL)
1918 edit_refresh();
1919
Chris Allegretta17dcb722001-01-20 21:40:07 +00001920 /* Restore totsize from befure justify */
1921 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00001922 free_filestruct(tmptop);
1923 blank_statusbar_refresh();
1924 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00001925 shortcut_init(0);
1926 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00001927 free_filestruct(cutbuffer);
1928 cutbuffer = cutbak;
1929
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001930 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001931#endif
1932}
1933
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001934#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001935void help_init(void)
1936{
1937 int i, sofar = 0;
1938 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegretta220ba692000-12-18 03:40:00 +00001939 char buf[BUFSIZ] = "";
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001940
1941 /* Compute the space needed for the shortcut lists - we add 15 to
1942 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegretta220ba692000-12-18 03:40:00 +00001943 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001944 if (main_list[i].help != NULL)
1945 allocsize += strlen(main_list[i].help) + 15;
1946
Chris Allegretta756f2202000-09-01 13:32:47 +00001947 /* And for the toggle list, we also allocate space for extra text. */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00001948 for (i = 0; i <= TOGGLE_LEN - 1; i++)
Chris Allegretta756f2202000-09-01 13:32:47 +00001949 if (toggles[i].desc != NULL)
1950 allocsize += strlen(toggles[i].desc) + 30;
1951
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001952 allocsize += strlen(help_text_init);
1953
1954 if (help_text != NULL)
1955 free(help_text);
1956
1957 /* Allocate space for the help text */
1958 help_text = nmalloc(allocsize);
1959
1960 /* Now add the text we want */
1961 strcpy(help_text, help_text_init);
1962
1963 /* Now add our shortcut info */
Chris Allegretta220ba692000-12-18 03:40:00 +00001964 for (i = 0; i <= MAIN_LIST_LEN - 1; i++) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001965 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001966
1967 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00001968 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001969 main_list[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001970 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001971 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001972
1973 if (main_list[i].altval > 0)
Chris Allegrettae49f1232000-09-02 07:20:39 +00001974 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001975 main_list[i].altval - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001976 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001977 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001978
Chris Allegretta756f2202000-09-01 13:32:47 +00001979
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001980 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00001981 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001982
Chris Allegretta756f2202000-09-01 13:32:47 +00001983
1984 strcat(help_text, buf);
1985 strcat(help_text, "\n");
1986 }
1987
1988 /* And the toggles... */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00001989 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001990 sofar = snprintf(buf, BUFSIZ,
1991 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00001992
1993 if (toggles[i].desc != NULL)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001994 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
1995 toggles[i].desc);
Chris Allegretta756f2202000-09-01 13:32:47 +00001996
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001997 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00001998 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001999 }
2000
2001}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002002#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002003
Chris Allegretta756f2202000-09-01 13:32:47 +00002004void do_toggle(int which)
2005{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002006#ifdef NANO_SMALL
2007 nano_disabled_msg();
2008#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002009 char *enabled = _("enabled");
2010 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002011
Chris Allegretta2a42af12000-09-12 23:02:49 +00002012 if (ISSET(toggles[which].flag))
Chris Allegretta756f2202000-09-01 13:32:47 +00002013 UNSET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002014 else
Chris Allegretta756f2202000-09-01 13:32:47 +00002015 SET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002016
Chris Allegretta756f2202000-09-01 13:32:47 +00002017 switch (toggles[which].val) {
2018 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002019 shortcut_init(0);
Chris Allegretta756f2202000-09-01 13:32:47 +00002020 display_main_list();
2021 break;
2022 case TOGGLE_SUSPEND_KEY:
2023 signal_init();
2024 break;
2025 case TOGGLE_MOUSE_KEY:
2026 mouse_init();
2027 break;
2028 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002029 wclear(bottomwin);
2030 wrefresh(bottomwin);
2031 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002032 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002033 edit_refresh();
2034 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002035 break;
2036 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002037
2038 if (!ISSET(toggles[which].flag)) {
2039 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002040 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002041 statusbar("%s %s", toggles[which].desc, enabled);
2042 else
2043 statusbar("%s %s", toggles[which].desc, disabled);
2044 } else {
2045 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002046 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002047 statusbar("%s %s", toggles[which].desc, disabled);
2048 else
2049 statusbar("%s %s", toggles[which].desc, enabled);
2050 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002051 SET(DISABLE_CURPOS);
2052
2053#endif
2054}
2055
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002056/* If the NumLock key has made the keypad gone awry, print an error
2057 message, hopefully we can address it later. */
2058void print_numlock_warning(void)
2059{
2060 static int didmsg = 0;
2061 if (!didmsg) {
Chris Allegretta40973792001-01-15 20:25:24 +00002062 statusbar(_("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002063 didmsg = 1;
2064 }
2065}
2066
Chris Allegretta1748cd12001-01-13 17:22:54 +00002067/* This function returns the correct keystroke, given the A,B,C or D
2068 input key. This is a common sequence of many terms which send
2069 Esc-O-[A-D] or Esc-[-[A-D]. */
2070int ABCD(int input)
2071{
2072 switch(input)
2073 {
2074 case 'A':
2075 return(KEY_UP);
2076 case 'B':
2077 return(KEY_DOWN);
2078 case 'C':
2079 return(KEY_RIGHT);
2080 case 'D':
2081 return(KEY_LEFT);
2082 default:
2083 return 0;
2084 }
2085}
2086
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002087int main(int argc, char *argv[])
2088{
2089 int optchr;
2090 int kbinput; /* Input from keyboard */
2091 long startline = 0; /* Line to try and start at */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002092 int keyhandled = 0; /* Have we handled the keystroke yet? */
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002093 int i, modify_control_seq = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002094 char *argv0;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002095#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002096 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002097#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002098
2099#ifdef HAVE_GETOPT_LONG
2100 int option_index = 0;
2101 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002102#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002103 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002104#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002105 {"version", 0, 0, 'V'},
2106 {"const", 0, 0, 'c'},
2107 {"suspend", 0, 0, 'z'},
2108 {"nowrap", 0, 0, 'w'},
2109 {"nohelp", 0, 0, 'x'},
2110 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002111 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002112#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002113 {"cut", 0, 0, 'k'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002114#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002115 {"autoindent", 0, 0, 'i'},
2116 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002117#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002118 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002119#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002120 {"fill", 1, 0, 'r'},
2121 {"mouse", 0, 0, 'm'},
2122 {"pico", 0, 0, 'p'},
2123 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002124 {"tabsize", 1, 0, 'T'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002125 {0, 0, 0, 0}
2126 };
2127#endif
2128
2129 /* Flag inits... */
2130 SET(FOLLOW_SYMLINKS);
2131
2132#ifndef NANO_SMALL
2133 setlocale(LC_ALL, "");
2134 bindtextdomain(PACKAGE, LOCALEDIR);
2135 textdomain(PACKAGE);
2136#endif
2137
2138#ifdef HAVE_GETOPT_LONG
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002139 while ((optchr = getopt_long(argc, argv, "?T:RVbcefhiklmpr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002140 long_options, &option_index)) != EOF) {
2141#else
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002142 while ((optchr = getopt(argc, argv, "h?T:RVbcefiklmpr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002143#endif
2144
2145 switch (optchr) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002146 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002147 tabsize = atoi(optarg);
2148 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002149 usage(); /* To stop bogus data for tab width */
2150 finish(1);
2151 }
2152 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002153#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002154 case 'R':
2155 SET(USE_REGEXP);
2156 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002157#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002158 case 'V':
2159 version();
2160 exit(0);
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002161 case 'b':
2162 case 'e':
2163 case 'f':
2164 /* Pico compatibility flags */
2165 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002166 case 'c':
2167 SET(CONSTUPDATE);
2168 break;
2169 case 'h':
2170 case '?':
2171 usage();
2172 exit(0);
2173 case 'i':
2174 SET(AUTOINDENT);
2175 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002176#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002177 case 'k':
2178 SET(CUT_TO_END);
2179 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002180#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002181 case 'l':
2182 UNSET(FOLLOW_SYMLINKS);
2183 break;
2184 case 'm':
2185 SET(USE_MOUSE);
2186 break;
2187 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002188 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002189 break;
2190 case 'r':
2191 fill = atoi(optarg);
2192 if (fill <= 0) {
2193 usage(); /* To stop bogus data (like a string) */
2194 finish(1);
2195 }
2196 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002197#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002198 case 's':
2199 alt_speller = nmalloc(strlen(optarg) + 1);
2200 strcpy(alt_speller, optarg);
2201 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002202#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002203 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002204 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002205 break;
2206 case 'v':
2207 SET(VIEW_MODE);
2208 break;
2209 case 'w':
2210 SET(NO_WRAP);
2211 break;
2212 case 'x':
2213 SET(NO_HELP);
2214 break;
2215 case 'z':
2216 SET(SUSPEND);
2217 break;
2218 default:
2219 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002220 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002221 }
2222
2223 }
2224
2225 argv0 = strrchr(argv[0], '/');
2226 if ((argv0 && strstr(argv0, "pico"))
2227 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002228 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002229
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002230 /* See if there's a non-option in argv (first non-option is the
2231 filename, if +LINE is not given) */
2232 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002233 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002234 else {
2235 /* Look for the +line flag... */
2236 if (argv[optind][0] == '+') {
2237 startline = atoi(&argv[optind][1]);
2238 optind++;
2239 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002240 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002241 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002242 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002243
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002244 } else
2245 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002246 }
2247
2248
2249 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002250 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002251
Chris Allegretta9239d742000-09-06 15:19:18 +00002252#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002253 term = oldterm;
2254 term.c_cc[VINTR] = _POSIX_VDISABLE;
2255 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2256 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002257 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002258#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002259
2260 /* now ncurses init stuff... */
2261 initscr();
2262 savetty();
2263 nonl();
2264 cbreak();
2265 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002266
2267 /* Set up some global variables */
2268 global_init();
Chris Allegretta07798352000-11-27 22:58:23 +00002269 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002270#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002271 init_help_msg();
2272 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002273#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002274 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002275
2276#ifdef DEBUG
2277 fprintf(stderr, _("Main: set up windows\n"));
2278#endif
2279
Chris Allegretta2a42af12000-09-12 23:02:49 +00002280 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002281 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002282
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002283#ifdef DEBUG
2284 fprintf(stderr, _("Main: bottom win\n"));
2285#endif
2286 /* Set up up bottom of window */
2287 display_main_list();
2288
2289#ifdef DEBUG
2290 fprintf(stderr, _("Main: open file\n"));
2291#endif
2292
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002293 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00002294
2295 /* Now we check to see if argv[optind] is non-null to determine if
2296 we're dealing with a new file or not, not argc == 1... */
2297 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002298 new_file();
2299 else
2300 open_file(filename, 0, 0);
2301
2302 if (startline > 0)
2303 do_gotoline(startline);
2304 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002305 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002306
Robert Siemborski6967eec2000-07-08 14:23:32 +00002307 edit_refresh();
2308 reset_cursor();
2309
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002310 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00002311
2312#ifndef _POSIX_VDISABLE
2313 /* We're going to have to do it the old way, i.e. on cygwin */
2314 raw();
2315#endif
2316
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002317 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002318#ifdef DEBUG
2319 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
2320#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002321 if (kbinput == 27) { /* Grab Alt-key stuff first */
2322 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002323 /* Alt-O, suddenly very important ;) */
Chris Allegretta16e41682000-09-11 22:33:54 +00002324 case 79:
2325 kbinput = wgetch(edit);
Chris Allegretta1748cd12001-01-13 17:22:54 +00002326 if (kbinput <= 'D' && kbinput >= 'A')
2327 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002328 else if (kbinput <= 'z' && kbinput >= 'j')
2329 print_numlock_warning();
2330 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002331 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002332#ifdef DEBUG
2333 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002334 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2335 kbinput, kbinput);
2336 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002337 }
2338#endif
2339 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002340 case 27:
2341 /* If we get Alt-Alt, the next keystroke should be the same as a
2342 control sequence */
2343 modify_control_seq = 1;
2344 keyhandled = 1;
2345 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002346 case 91:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002347 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002348 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00002349 kbinput = wgetch(edit);
2350 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002351 kbinput = KEY_F(kbinput - 48);
2352 wgetch(edit);
2353 } else if (kbinput >= '7' && kbinput <= '9') {
2354 kbinput = KEY_F(kbinput - 49);
2355 wgetch(edit);
2356 } else if (kbinput == 126)
2357 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00002358
2359#ifdef DEBUG
2360 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002361 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
2362 kbinput, kbinput);
2363 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002364 }
2365#endif
2366
2367 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002368 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00002369 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00002370 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002371 case '0':
2372 kbinput = KEY_F(9);
2373 wgetch(edit);
2374 break;
2375 case '1':
2376 kbinput = KEY_F(10);
2377 wgetch(edit);
2378 break;
2379 case '3':
2380 kbinput = KEY_F(11);
2381 wgetch(edit);
2382 break;
2383 case '4':
2384 kbinput = KEY_F(12);
2385 wgetch(edit);
2386 break;
2387 case 126: /* Hack, make insert key do something
2388 usefile, like insert file */
2389 do_insertfile();
2390 keyhandled = 1;
2391 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002392#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002393 default:
2394 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
2395 kbinput, kbinput);
2396 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002397#endif
2398
2399 }
2400 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002401 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002402 kbinput = NANO_DELETE_KEY;
2403 wgetch(edit);
2404 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002405 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002406 kbinput = NANO_END_KEY;
2407 wgetch(edit);
2408 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002409 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00002410 kbinput = KEY_PPAGE;
2411 wgetch(edit);
2412 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002413 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00002414 kbinput = KEY_NPAGE;
2415 wgetch(edit);
2416 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002417 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00002418 kbinput = wgetch(edit);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002419 if (kbinput >= 'A' && kbinput <= 'E')
2420 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00002421 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002422 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002423 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002424 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002425 case 'D':
Chris Allegretta1748cd12001-01-13 17:22:54 +00002426 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002427 break;
2428 case 'H':
2429 kbinput = KEY_HOME;
2430 break;
2431 case 'F':
2432 kbinput = KEY_END;
2433 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002434 default:
2435#ifdef DEBUG
2436 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
2437 kbinput, kbinput);
2438#endif
2439 break;
2440 }
2441 break;
2442 default:
2443
2444 /* Check for the altkey defs.... */
2445 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
2446 if (kbinput == main_list[i].altval ||
2447 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002448 kbinput = main_list[i].val;
2449 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002450 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002451#ifndef NANO_SMALL
2452 /* And for toggle switches */
2453 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
2454 if (kbinput == toggles[i].val ||
2455 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002456 do_toggle(i);
2457 keyhandled = 1;
2458 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002459 }
2460#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002461#ifdef DEBUG
2462 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
2463 kbinput);
2464#endif
2465 break;
2466 }
2467 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002468 /* If the modify_control_seq is set, we received an Alt-Alt
2469 sequence before this, so we make this key a control sequence
2470 by subtracting 64 or 96, depending on its value. */
2471 if (!keyhandled && modify_control_seq) {
2472 if (kbinput >= 'A' && kbinput < 'a')
2473 kbinput -= 64;
2474 else if (kbinput >= 'a' && kbinput <= 'z')
2475 kbinput -= 96;
2476
2477 modify_control_seq = 0;
2478 }
2479
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002480 /* Look through the main shortcut list to see if we've hit a
2481 shortcut key */
Chris Allegretta756f2202000-09-01 13:32:47 +00002482 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002483 if (kbinput == main_list[i].val ||
2484 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
2485 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
2486 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
2487 print_view_warning();
2488 else
2489 main_list[i].func();
2490 keyhandled = 1;
2491 }
2492 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002493 /* If we're in raw mode or using Alt-Alt-x, we have to catch
2494 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00002495 if (kbinput == 17 || kbinput == 19)
2496 keyhandled = 1;
2497
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002498 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00002499 if (kbinput == 26) {
2500 if (ISSET(SUSPEND))
2501 do_suspend(0);
2502 keyhandled = 1;
2503 }
Chris Allegretta9239d742000-09-06 15:19:18 +00002504
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002505 /* Last gasp, stuff that's not in the main lists */
2506 if (!keyhandled)
2507 switch (kbinput) {
2508#ifndef NANO_SMALL
2509#ifdef NCURSES_MOUSE_VERSION
2510 case KEY_MOUSE:
2511 do_mouse();
2512 break;
2513#endif
2514#endif
2515 case 0: /* Erg */
2516 do_next_word();
2517 break;
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00002518
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002519 case 331: /* Stuff that we don't want to do squat */
2520 case -1:
2521 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002522#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002523 case 541: /* ???? */
2524 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00002525 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002526 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00002527 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002528#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002529
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002530 break;
2531 default:
2532#ifdef DEBUG
2533 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
2534#endif
2535 /* We no longer stop unhandled sequences so that people with
2536 odd character sets can type... */
2537
2538 if (ISSET(VIEW_MODE)) {
2539 print_view_warning();
2540 break;
2541 }
2542 do_char(kbinput);
2543 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002544 if (ISSET(CONSTUPDATE)) {
2545 if (ISSET(DISABLE_CURPOS))
2546 UNSET(DISABLE_CURPOS);
2547 else
2548 do_cursorpos();
2549 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002550
2551 reset_cursor();
2552 wrefresh(edit);
2553 keyhandled = 0;
2554 }
2555
2556 getchar();
2557 finish(0);
2558
2559}