blob: d133ab4d9a2bd0038f689fb737575c3d0d7ed599 [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>
Chris Allegretta08020882001-01-29 23:37:54 +000026#include <setjmp.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000027#include <unistd.h>
28#include <string.h>
29#include <fcntl.h>
30#include <sys/stat.h>
31#include <sys/ioctl.h>
32#include <sys/param.h>
Chris Allegretta27eb13f2000-11-05 16:52:21 +000033#include <sys/types.h>
34#include <sys/wait.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000035#include <errno.h>
36#include <ctype.h>
37#include <locale.h>
38#include <limits.h>
Adam Rogoyski77f36de2000-06-07 03:56:54 +000039#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000040
41#include "config.h"
42#include "proto.h"
43#include "nano.h"
44
45#ifndef NANO_SMALL
46#include <libintl.h>
47#define _(string) gettext(string)
48#else
49#define _(string) (string)
50#endif
51
52#ifdef HAVE_TERMIOS_H
53#include <termios.h>
54#endif
55
56#ifdef HAVE_TERMIO_H
57#include <termio.h>
58#endif
59
60#ifdef HAVE_GETOPT_H
61#include <getopt.h>
62#endif
63
64/* Former globals, now static */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000065int fill = 0; /* Fill - where to wrap lines, basically */
Rocco Corsiaf5c3022001-01-12 07:51:05 +000066
67#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000068static char *alt_speller; /* Alternative spell command */
Rocco Corsiaf5c3022001-01-12 07:51:05 +000069#endif
70
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000071struct termios oldterm; /* The user's original term settings */
Chris Allegretta18f8be02000-09-04 03:20:38 +000072static struct sigaction act; /* For all out fun signal handlers */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000073
Rocco Corsiaf5c3022001-01-12 07:51:05 +000074#ifndef DISABLE_HELP
Chris Allegretta65121632000-12-18 07:05:27 +000075static char *help_text_init = ""; /* Initial message, not including shortcuts */
76#endif
77
Chris Allegretta27eb13f2000-11-05 16:52:21 +000078char *last_search = NULL; /* Last string we searched for */
79char *last_replace = NULL; /* Last replacement string */
80int search_last_line; /* Is this the last search line? */
81
Chris Allegretta08020882001-01-29 23:37:54 +000082static sigjmp_buf jmpbuf; /* Used to return to mainloop after SIGWINCH */
83
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000084/* What we do when we're all set to exit */
85RETSIGTYPE finish(int sigage)
86{
Chris Allegrettac08f50d2001-01-06 18:12:43 +000087
88 keypad(edit, TRUE);
89 keypad(bottomwin, TRUE);
90
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000091 if (!ISSET(NO_HELP)) {
92 mvwaddstr(bottomwin, 1, 0, hblank);
93 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000094 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000095 mvwaddstr(bottomwin, 0, 0, hblank);
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +000096
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000097 wrefresh(bottomwin);
98 endwin();
99
100 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000101 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000102
103 exit(sigage);
104}
105
106/* Die (gracefully?) */
107void die(char *msg, ...)
108{
109 va_list ap;
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000110 char *name;
111 int i;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000112
113 va_start(ap, msg);
114 vfprintf(stderr, msg, ap);
115 va_end(ap);
116
117 /* if we can't save we have REAL bad problems,
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000118 * but we might as well TRY. */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000119 if (filename[0] == '\0') {
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000120 name = "nano.save";
121 i = write_file(name, 1);
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000122 } else {
Chris Allegrettae7a58932000-12-02 02:36:22 +0000123
124 char *buf = nmalloc(strlen(filename) + 6);
125 strcpy(buf, filename);
126 strcat(buf, ".save");
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000127 i = write_file(buf, 1);
128 name = buf;
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000129 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000130 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000131 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000132
133 clear();
134 refresh();
135 resetty();
136 endwin();
137
138 fprintf(stderr, msg);
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000139 if (i != -1)
140 fprintf(stderr, _("\nBuffer written to %s\n"), name);
141 else
Chris Allegretta9756d622000-12-03 03:06:45 +0000142 fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000143
144 exit(1); /* We have a problem: exit w/ errorlevel(1) */
145}
146
Chris Allegrettae61e8302001-01-14 05:18:27 +0000147/* Die with an error message that the screen was too small if, well, the
148 screen is too small */
149void die_too_small(void)
150{
151 char *too_small_msg = _("Window size is too small for Nano...");
152
153 die(too_small_msg);
154
155}
156
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000157void print_view_warning(void)
158{
159 statusbar(_("Key illegal in VIEW mode"));
160}
161
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000162void clear_filename(void)
163{
164 if (filename != NULL)
165 free(filename);
166 filename = nmalloc(1);
167 filename[0] = 0;
168}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000169
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000170/* Initialize global variables - no better way for now */
171void global_init(void)
172{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000173 current_x = 0;
174 current_y = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000175
176 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
177 die_too_small();
178
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000179 fileage = NULL;
180 cutbuffer = NULL;
181 current = NULL;
182 edittop = NULL;
183 editbot = NULL;
184 totlines = 0;
185 placewewant = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000186
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000187 if (!fill)
Chris Allegrettae61e8302001-01-14 05:18:27 +0000188 fill = COLS - CHARS_FROM_EOL;
189
190 if (fill < MIN_FILL_LENGTH)
191 die_too_small();
192
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000193 hblank = nmalloc(COLS + 1);
Chris Allegretta0a06e072001-01-23 02:35:04 +0000194 memset(hblank, ' ', COLS);
195 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000196}
197
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000198#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000199void init_help_msg(void)
200{
201
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000202 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000203 _(" nano help text\n\n "
204 "The nano editor is designed to emulate the functionality and "
205 "ease-of-use of the UW Pico text editor. There are four main "
206 "sections of the editor: The top line shows the program "
207 "version, the current filename being edited, and whether "
208 "or not the file has been modified. Next is the main editor "
209 "window showing the file being edited. The status line is "
210 "the third line from the bottom and shows important messages. "
211 "The bottom two lines show the most commonly used shortcuts "
212 "in the editor.\n\n "
213 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000214 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000215 "with the Control (Ctrl) key. Escape-key sequences are notated "
216 "with the Meta (M) symbol and can be entered using either the "
217 "Esc, Alt or Meta key depending on your keyboard setup. The "
218 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000219 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000220
221}
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000222#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000223
224/* Make a copy of a node to a pointer (space will be malloc()ed) */
225filestruct *copy_node(filestruct * src)
226{
227 filestruct *dst;
228
229 dst = nmalloc(sizeof(filestruct));
230 dst->data = nmalloc(strlen(src->data) + 1);
231
232 dst->next = src->next;
233 dst->prev = src->prev;
234
235 strcpy(dst->data, src->data);
236 dst->lineno = src->lineno;
237
238 return dst;
239}
240
241/* Unlink a node from the rest of the struct */
242void unlink_node(filestruct * fileptr)
243{
244 if (fileptr->prev != NULL)
245 fileptr->prev->next = fileptr->next;
246
247 if (fileptr->next != NULL)
248 fileptr->next->prev = fileptr->prev;
249}
250
251void delete_node(filestruct * fileptr)
252{
Chris Allegretta17dcb722001-01-20 21:40:07 +0000253 if (fileptr == NULL)
254 return;
255
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000256 if (fileptr->data != NULL)
Chris Allegretta17dcb722001-01-20 21:40:07 +0000257 free(fileptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000258 free(fileptr);
259}
260
261/* Okay, now let's duplicate a whole struct! */
262filestruct *copy_filestruct(filestruct * src)
263{
264 filestruct *dst, *tmp, *head, *prev;
265
266 head = copy_node(src);
267 dst = head; /* Else we barf on copying just one line */
268 head->prev = NULL;
269 tmp = src->next;
270 prev = head;
271
272 while (tmp != NULL) {
273 dst = copy_node(tmp);
274 dst->prev = prev;
275 prev->next = dst;
276
277 prev = dst;
278 tmp = tmp->next;
279 }
280
281 dst->next = NULL;
282 return head;
283}
284
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000285int free_filestruct(filestruct * src)
286{
287 filestruct *fileptr = src;
288
289 if (src == NULL)
290 return 0;
291
292 while (fileptr->next != NULL) {
293 fileptr = fileptr->next;
Chris Allegretta17dcb722001-01-20 21:40:07 +0000294 delete_node(fileptr->prev);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000295
296#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000297 fprintf(stderr, _("delete_node(): free'd a node, YAY!\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000298#endif
299 }
Chris Allegretta17dcb722001-01-20 21:40:07 +0000300 delete_node(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000301#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000302 fprintf(stderr, _("delete_node(): free'd last node.\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000303#endif
304
305 return 1;
306}
307
308int renumber_all(void)
309{
310 filestruct *temp;
311 long i = 1;
312
313 for (temp = fileage; temp != NULL; temp = temp->next) {
314 temp->lineno = i++;
315 }
316
317 return 0;
318}
319
320int renumber(filestruct * fileptr)
321{
322 filestruct *temp;
323
324 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
325 renumber_all();
326 return 0;
327 }
328 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000329 if (temp->prev != NULL)
330 temp->lineno = temp->prev->lineno + 1;
331 else
332 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000333 }
334
335 return 0;
336}
337
338/* Fix the memory allocation for a string */
339void align(char **strp)
340{
341 /* There was a serious bug here: the new address was never
342 stored anywhere... */
343
344 *strp = nrealloc(*strp, strlen(*strp) + 1);
345}
346
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000347/* Null a string at a certain index and align it */
348void null_at(char *data, int index)
349{
350 data[index] = 0;
351 align(&data);
352}
353
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000354void usage(void)
355{
356#ifdef HAVE_GETOPT_LONG
357 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
358 printf(_("Option Long option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000359 printf(_
Chris Allegrettae9a2d032001-01-21 16:08:21 +0000360 (" -T [num] --tabsize=[num] Set width of a tab to num\n"));
Chris Allegretta805c26d2000-09-06 13:39:17 +0000361#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000362 printf(_
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000363 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000364#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000365 printf
366 (_
367 (" -V --version Print version information and exit\n"));
368 printf(_
369 (" -c --const Constantly show cursor position\n"));
370 printf(_
371 (" -h --help Show this message\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000372 printf(_
373 (" -i --autoindent Automatically indent new lines\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000374#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000375 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000376 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000377#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000378 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000379 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000380#ifndef NANO_SMALL
381#ifdef NCURSES_MOUSE_VERSION
382 printf(_(" -m --mouse Enable mouse\n"));
383#endif
384#endif
Chris Allegrettad55655f2000-12-27 03:36:47 +0000385 printf(_
386 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000387 printf
388 (_
389 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000390#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000391 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000392 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000393#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000394 printf(_
395 (" -t --tempfile Auto save on exit, don't prompt\n"));
396 printf(_
397 (" -v --view View (read only) mode\n"));
398 printf(_
399 (" -w --nowrap Don't wrap long lines\n"));
400 printf(_
401 (" -x --nohelp Don't show help window\n"));
402 printf(_
403 (" -z --suspend Enable suspend\n"));
404 printf(_
405 (" +LINE Start at line number LINE\n"));
406#else
407 printf(_("Usage: nano [option] +LINE <file>\n\n"));
408 printf(_("Option Meaning\n"));
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000409 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000410 printf(_(" -R Use regular expressions for search\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000411 printf(_(" -V Print version information and exit\n"));
412 printf(_(" -c Constantly show cursor position\n"));
413 printf(_(" -h Show this message\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000414 printf(_(" -i Automatically indent new lines\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000415#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +0000416 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000417#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000418 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000419 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000420#ifndef NANO_SMALL
421#ifdef NCURSES_MOUSE_VERSION
422 printf(_(" -m Enable mouse\n"));
423#endif
424#endif
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000425 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000426 printf(_(" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000427#ifndef DISABLE_SPELLER
Chris Allegrettad55655f2000-12-27 03:36:47 +0000428 printf(_(" -s [prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000429#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000430 printf(_(" -t Auto save on exit, don't prompt\n"));
431 printf(_(" -v View (read only) mode\n"));
432 printf(_(" -w Don't wrap long lines\n"));
433 printf(_(" -x Don't show help window\n"));
434 printf(_(" -z Enable suspend\n"));
435 printf(_(" +LINE Start at line number LINE\n"));
436#endif
437 exit(0);
438}
439
440void version(void)
441{
442 printf(_(" nano version %s by Chris Allegretta (compiled %s, %s)\n"),
443 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000444 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000445 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000446 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000447
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000448#ifdef NANO_EXTRA
449 printf(" --enable-extra");
450#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000451
452#ifdef NANO_SMALL
453 printf(" --enable-tiny");
454#else
455 #ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000456 printf(" --disable-browser");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000457 #endif
458 #ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000459 printf(" --disable-tabcomp");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000460 #endif
461 #ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000462 printf(" --disable-justify");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000463 #endif
464 #ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000465 printf(" --disable-speller");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000466 #endif
467 #ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000468 printf(" --disable-help");
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000469 #endif
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000470#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000471
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000472#ifdef USE_SLANG
473 printf(" --with-slang");
474#endif
475 printf("\n");
476
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000477}
478
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000479filestruct *make_new_node(filestruct * prevnode)
480{
481 filestruct *newnode;
482
483 newnode = nmalloc(sizeof(filestruct));
484 newnode->data = NULL;
485
486 newnode->prev = prevnode;
487 newnode->next = NULL;
488
489 if (prevnode != NULL)
490 newnode->lineno = prevnode->lineno + 1;
491
492 return newnode;
493}
494
Chris Allegretta7975ed82000-07-28 00:58:35 +0000495/* Splice a node into an existing filestruct */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000496void splice_node(filestruct * begin, filestruct * new, filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000497{
498 new->next = end;
499 new->prev = begin;
500 begin->next = new;
501 if (end != NULL)
502 end->prev = new;
503}
504
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000505int do_mark()
506{
507#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000508 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000509#else
510 if (!ISSET(MARK_ISSET)) {
511 statusbar(_("Mark Set"));
512 SET(MARK_ISSET);
513 mark_beginbuf = current;
514 mark_beginx = current_x;
515 } else {
516 statusbar(_("Mark UNset"));
517 UNSET(MARK_ISSET);
518 mark_beginbuf = NULL;
519 mark_beginx = 0;
520
521 edit_refresh();
522 }
523#endif
524 return 1;
525}
526
527int no_help(void)
528{
529 if ISSET
530 (NO_HELP)
531 return 2;
532 else
533 return 0;
534}
535
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000536#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000537void nano_disabled_msg(void)
538{
539 statusbar("Sorry, support for this function has been disabled");
540}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000541#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000542
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000543/* The user typed a printable character; add it to the edit buffer */
544void do_char(char ch)
545{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000546 /* magic-line: when a character is inserted on the current magic line,
547 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000548 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000549 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000550 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000551 }
552
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000553 /* More dangerousness fun =) */
554 current->data = nrealloc(current->data, strlen(current->data) + 2);
555 memmove(&current->data[current_x + 1],
556 &current->data[current_x],
557 strlen(current->data) - current_x + 1);
558 current->data[current_x] = ch;
559 do_right();
560
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000561 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000562 check_wrap(current, ch);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000563 set_modified();
564 check_statblank();
565 UNSET(KEEP_CUTBUFFER);
566 totsize++;
567
568}
569
570/* Someone hits return *gasp!* */
571int do_enter(filestruct * inptr)
572{
573 filestruct *new;
574 char *tmp, *spc;
575 int extra = 0;
576
577 new = make_new_node(inptr);
578 tmp = &current->data[current_x];
579 current_x = 0;
580
581 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
582 if (ISSET(AUTOINDENT)) {
583 spc = current->data;
584 if (spc) {
585 while ((*spc == ' ') || (*spc == '\t')) {
586 extra++;
587 spc++;
588 current_x++;
589 }
590 new->data = nmalloc(strlen(tmp) + extra + 1);
591 strncpy(new->data, current->data, extra);
592 strcpy(&new->data[extra], tmp);
593 }
594 } else {
595 new->data = nmalloc(strlen(tmp) + 1);
596 strcpy(new->data, tmp);
597 }
598 *tmp = 0;
599
Chris Allegrettada721be2000-07-31 01:26:42 +0000600 if (inptr->next == NULL) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000601 filebot = new;
602 editbot = new;
603 }
Chris Allegretta7975ed82000-07-28 00:58:35 +0000604 splice_node(inptr, new, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000605
606 totsize++;
607 renumber(current);
608 current = new;
609 align(&current->data);
610
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000611 /* The logic here is as follows:
612 * -> If we are at the bottom of the buffer, we want to recenter
613 * (read: rebuild) the screen and forcably move the cursor.
614 * -> otherwise, we want simply to redraw the screen and update
615 * where we think the cursor is.
616 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000617 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000618 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000619 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000620 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000621 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000622 edit_refresh();
623 update_cursor();
624 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000625
626 totlines++;
627 set_modified();
628
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000629 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000630 return 1;
631}
632
633int do_enter_void(void)
634{
635 return do_enter(current);
636}
637
638void do_next_word(void)
639{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000640 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000641 int i;
642
643 if (current == NULL)
644 return;
645
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000646 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000647 i = current_x;
648 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
649 if (fileptr == current) {
650 while (isalnum((int) fileptr->data[i])
651 && fileptr->data[i] != 0)
652 i++;
653
654 if (fileptr->data[i] == 0) {
655 i = 0;
656 continue;
657 }
658 }
659 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
660 i++;
661
662 if (fileptr->data[i] != 0)
663 break;
664
665 i = 0;
666 }
667 if (fileptr == NULL)
668 current = filebot;
669 else
670 current = fileptr;
671
672 current_x = i;
673 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000674
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000675 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000676 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000677 else {
678 /* If we've jumped lines, refresh the old line. We can't just use
679 * current->prev here, because we may have skipped over some blank
680 * lines, in which case the previous line is the wrong one.
681 */
682 if (current != old)
683 update_line(old, 0);
684
685 update_line(current, current_x);
686 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000687
688}
689
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000690void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000691{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000692 int i = 0; /* Index into ->data for line. */
693 int i_tabs = 0; /* Screen position of ->data[i]. */
694 int last_word_end = -1; /* Location of end of last word found. */
695 int current_word_start = -1; /* Location of start of current word. */
696 int current_word_start_t = -1; /* Location of start of current word screen position. */
697 int current_word_end = -1; /* Location of end of current word */
698 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000699 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000700
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000701 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000702 int right = 0;
703 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000704
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000705 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000706
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000707 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000708 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000709 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000710
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000711 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000712 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000713
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000714 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000715 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000716 i++;
717 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000718 if (inptr->data[i] < 32)
719 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000720 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000721
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000722 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000723 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000724 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000725 } else {
726 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000727 current_word_end_t = i_tabs - 1;
728 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000729 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000730
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000731 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000732 if (i_tabs % tabsize != 0);
733 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000734 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000735
Adam Rogoyski09f97962000-06-20 02:50:33 +0000736 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000737 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000738 }
739
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000740 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000741 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000742 * a) one word takes up the whole line with no starting spaces.
743 * - do nothing and return.
744 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000745 * - word starts new line.
746 * - keep white space on original line up to the cursor.
747 * *) cursor is after word at wrap point
748 * - either it's all white space after word, and this routine isn't called.
749 * - or we are actually in case 2 (2 words).
750 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000751 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000752 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000753 * - white space at end of original line is cleared, unless
754 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000755 * b) cursor is at the word at the wrap point.
756 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000757 * 1. pressed a space and at first character of wrap point word.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000758 * - white space on original line is kept to where cursor was.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000759 * 2. pressed non space (or space elsewhere).
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000760 * - white space at end of original line is cleared.
761 * c) cursor is past the word at the wrap point.
762 * - word at wrap point starts a new line.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000763 * - white space at end of original line is cleared
764 */
765
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000766 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000767
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000768 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000769 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000770 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000771 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000772 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000773 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000774 i++;
775 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000776 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000777 current_word_end = i;
778 break;
779 }
780 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000781
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000782 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000783 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000784 return;
785 }
786 if (current_x >= last_word_end) {
787 right = (current_x - current_word_start) + 1;
788 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000789 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000790 }
791
792 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
793 strcpy(temp->data, &inptr->data[current_word_start]);
794 inptr->data = nrealloc(inptr->data, last_word_end + 2);
795 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000796 } else
797 /* Category 1b: one word on the line and word not taking up whole line
798 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000799 if (last_word_end == -1) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000800 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
801 strcpy(temp->data, &inptr->data[current_word_start]);
802
803 /* Inside word, remove it from original, and move cursor to right spot. */
804 if (current_x >= current_word_start) {
805 right = current_x - current_word_start;
806 current_x = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000807 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000808 }
809
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000810 null_at(inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000811
812 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
813 mark_beginbuf = temp;
814 mark_beginx = 0;
815 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000816 }
817
818 /* Category 2: two or more words on the line. */
819 else {
820
821 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000822 if (current_x < current_word_start) {
823 temp->data =
824 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
825 strcpy(temp->data, &inptr->data[current_word_start]);
826
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000827 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000828 i = current_word_start - 1;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000829 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000830 i--;
831 assert(i >= 0);
832 }
833 } else if (current_x <= last_word_end)
834 i = last_word_end - 1;
835 else
836 i = current_x;
837
838 inptr->data = nrealloc(inptr->data, i + 2);
839 inptr->data[i + 1] = 0;
840 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000841
842
843 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000844 else if ((current_x >= current_word_start)
845 && (current_x <= (current_word_end + 1))) {
846 temp->data =
847 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000848 strcpy(temp->data, &inptr->data[current_word_start]);
849
850 down = 1;
851
852 right = current_x - current_word_start;
853 i = current_word_start - 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000854 if (isspace((int) input_char)
855 && (current_x == current_word_start)) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000856 current_x = current_word_start;
857
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000858 null_at(inptr->data, current_word_start);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000859 } else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000860
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000861 while (isspace((int) inptr->data[i])) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000862 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000863 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000864 }
865 inptr->data = nrealloc(inptr->data, i + 2);
866 inptr->data[i + 1] = 0;
867 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000868 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000869
870
871 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000872 else {
873 temp->data =
874 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000875 strcpy(temp->data, &inptr->data[current_word_start]);
876
877 down = 1;
878 right = current_x - current_word_start;
879
880 current_x = current_word_start;
881 i = current_word_start - 1;
882
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000883 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000884 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000885 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000886 inptr->data = nrealloc(inptr->data, i + 2);
887 inptr->data[i + 1] = 0;
888 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000889 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000890 }
891
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000892 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000893 if (ISSET(SAMELINEWRAP) && inptr->next) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000894 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
895 char *p =
896 nmalloc(strlen(temp->data) + strlen(inptr->next->data) + 2);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000897 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000898
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000899 strcpy(p, temp->data);
900 strcat(p, " ");
901 strcat(p, inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000902
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000903 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000904 inptr->next->data = p;
905
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000906 free(temp->data);
907 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000908
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000909 current_x = old_x;
910 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000911 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000912 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000913 else {
914 temp->prev = inptr;
915 temp->next = inptr->next;
916
917 if (inptr->next)
918 inptr->next->prev = temp;
919 inptr->next = temp;
920
921 if (!temp->next)
922 filebot = temp;
923
924 SET(SAMELINEWRAP);
925 }
926
927
928 totlines++;
Robert Siemborskia417ddc2000-07-24 23:18:48 +0000929 /* Everything about it makes me want this line here but it causes
930 * totsize to be high by one for some reason. Sigh. (Rob) */
931 /* totsize++; */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000932
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000933 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +0000934 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000935
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000936
937 /* Move the cursor to the new line if appropriate. */
938 if (down) {
939 do_right();
940 }
941
942 /* Move the cursor to the correct spot in the line if appropriate. */
943 while (right--) {
944 do_right();
945 }
946
Chris Allegretta234a34d2000-07-29 04:33:38 +0000947 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000948 reset_cursor();
949 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000950}
951
952/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000953void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000954{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000955 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000956#ifdef DEBUG
957 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
958 inptr->data);
959#endif
960
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000961 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000962 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000963 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000964 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000965
966 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000967 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000968
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000969 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +0000970 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000971
Adam Rogoyski09f97962000-06-20 02:50:33 +0000972 if (!inptr->data[i])
973 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000974
Adam Rogoyski09f97962000-06-20 02:50:33 +0000975 /* String must be at least 1 character long. */
976 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000977 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +0000978 if (!char_found)
979 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000980 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000981 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000982 } else
983 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000984 }
Adam Rogoyski09f97962000-06-20 02:50:33 +0000985
986 if (char_found == 2)
987 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000988 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000989}
990
991/* Stuff we do when we abort from programs and want to clean up the
992 * screen. This doesnt do much right now.
993 */
994void do_early_abort(void)
995{
996 blank_statusbar_refresh();
997}
998
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000999int do_backspace(void)
1000{
1001 filestruct *previous, *tmp;
1002
1003 if (current_x != 0) {
1004 /* Let's get dangerous */
1005 memmove(&current->data[current_x - 1], &current->data[current_x],
1006 strlen(current->data) - current_x + 1);
1007#ifdef DEBUG
1008 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1009#endif
1010 align(&current->data);
1011 do_left();
1012 } else {
1013 if (current == fileage)
1014 return 0; /* Can't delete past top of file */
1015
1016 previous = current->prev;
1017 current_x = strlen(previous->data);
1018 previous->data = nrealloc(previous->data,
1019 strlen(previous->data) +
1020 strlen(current->data) + 1);
1021 strcat(previous->data, current->data);
1022
1023 tmp = current;
1024 unlink_node(current);
1025 delete_node(current);
1026 if (current == edittop) {
1027 if (previous->next)
1028 current = previous->next;
1029 else
1030 current = previous;
Chris Allegrettada721be2000-07-31 01:26:42 +00001031 page_up_center();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001032 } else {
1033 if (previous->next)
1034 current = previous->next;
1035 else
1036 current = previous;
1037 update_line(current, current_x);
1038 }
1039
1040 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001041 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001042 filebot = current;
1043 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001044
1045 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001046 line we're on now is NOT blank. if it is blank we
1047 can just use IT for the magic line. This is how Pico
1048 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001049 if (strcmp(current->data, "")) {
1050 new_magicline();
1051 fix_editbot();
1052 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001053 }
1054
1055 current = previous;
1056 renumber(current);
1057 previous_line();
1058 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001059#ifdef DEBUG
1060 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1061#endif
1062
1063 }
1064
1065 totsize--;
1066 set_modified();
1067 UNSET(KEEP_CUTBUFFER);
1068 edit_refresh();
1069 return 1;
1070}
1071
1072int do_delete(void)
1073{
1074 filestruct *foo;
1075
1076 if (current_x != strlen(current->data)) {
1077 /* Let's get dangerous */
1078 memmove(&current->data[current_x], &current->data[current_x + 1],
1079 strlen(current->data) - current_x);
1080
1081 align(&current->data);
1082
Chris Allegretta4ed13152001-02-10 17:50:50 +00001083 /* Now that we have a magic lnie again, we can check for both being
1084 on the line before filebot as well as at filebot */
1085 } else if (current->next != NULL && current->next != filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001086 current->data = nrealloc(current->data,
1087 strlen(current->data) +
1088 strlen(current->next->data) + 1);
1089 strcat(current->data, current->next->data);
1090
1091 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001092 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001093 filebot = current;
1094 editbot = current;
1095 }
1096
1097 unlink_node(foo);
1098 delete_node(foo);
1099 update_line(current, current_x);
1100
Chris Allegretta4ed13152001-02-10 17:50:50 +00001101 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001102 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001103 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001104 new_magicline();
1105 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001106 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001107 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001108 renumber(current);
1109 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001110 } else
1111 return 0;
1112
1113 totsize--;
1114 set_modified();
1115 UNSET(KEEP_CUTBUFFER);
1116 edit_refresh();
1117 return 1;
1118}
1119
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001120void wrap_reset(void)
1121{
1122 UNSET(SAMELINEWRAP);
1123}
1124
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001125#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001126
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001127int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001128{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001129 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001130 filestruct *begin;
1131 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001132
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001133 /* save where we are */
1134 begin = current;
1135 beginx = current_x + 1;
1136
1137 /* save the current search/replace strings */
1138 search_init_globals();
1139 save_search = mallocstrcpy(save_search, last_search);
1140 save_replace = mallocstrcpy(save_replace, last_replace);
1141
1142 /* set search/replace strings to mis-spelt word */
1143 prevanswer = mallocstrcpy(prevanswer, word);
1144 last_search = mallocstrcpy(last_search, word);
1145 last_replace = mallocstrcpy(last_replace, word);
1146
1147 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001148 current = fileage;
1149 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001150
1151 search_last_line = FALSE;
1152
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001153 edit_update(fileage, TOP);
1154
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001155 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001156 if (findnextstr(TRUE, fileage, beginx_top, prevanswer) != NULL)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001157 {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001158 do_replace_highlight(TRUE, prevanswer);
1159
1160 /* allow replace word to be corrected */
1161 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1162 _("Edit a replacement"));
1163
1164 do_replace_highlight(FALSE, prevanswer);
1165
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001166 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001167 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001168 current_x = beginx_top;
1169
1170 search_last_line = FALSE;
1171
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001172 j = i;
1173 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001174 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001175
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001176 /* restore the search/replace strings */
1177 last_search = mallocstrcpy(last_search, save_search);
1178 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001179
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001180 /* restore where we were */
1181 current = begin;
1182 current_x = beginx - 1;
1183
1184 edit_update(current, CENTER);
1185
1186 if (i == -1)
1187 return FALSE;
1188
1189 return TRUE;
1190}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001191
1192/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001193int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001194{
Chris Allegretta271e9722000-11-10 18:15:43 +00001195 char *read_buff, *read_buff_ptr, *read_buff_word;
1196 long pipe_buff_size;
1197 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001198 int spell_status;
1199 pid_t pid_spell;
1200 ssize_t bytesread;
1201
Chris Allegretta271e9722000-11-10 18:15:43 +00001202 /* Create a pipe to spell program */
1203
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001204 if (pipe(in_fd) == -1)
1205 return FALSE;
1206
Chris Allegretta271e9722000-11-10 18:15:43 +00001207 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001208
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001209 if ( (pid_spell = fork()) == 0) {
1210
1211 /* Child continues, (i.e. future spell process) */
1212
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001213 close(in_fd[0]);
1214
Chris Allegretta271e9722000-11-10 18:15:43 +00001215 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001216
Chris Allegretta271e9722000-11-10 18:15:43 +00001217 if ( (tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
1218
1219 close(in_fd[1]);
1220 exit(1);
1221 }
1222
1223 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1224
1225 close(tempfile_fd);
1226 close(in_fd[1]);
1227 exit(1);
1228 }
1229 close(tempfile_fd);
1230
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001231
Chris Allegretta271e9722000-11-10 18:15:43 +00001232 /* send spell's standard out to the pipe */
1233
1234 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1235
1236 close(in_fd[1]);
1237 exit(1);
1238 }
1239 close(in_fd[1]);
1240
1241 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001242 execlp("spell", "spell", NULL);
1243
Chris Allegretta271e9722000-11-10 18:15:43 +00001244 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001245
Chris Allegretta271e9722000-11-10 18:15:43 +00001246 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001247 }
1248
1249 /* Parent continues here */
1250
Chris Allegretta271e9722000-11-10 18:15:43 +00001251 close(in_fd[1]);
1252
1253 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001254
1255 if (pid_spell < 0) {
1256
Chris Allegretta271e9722000-11-10 18:15:43 +00001257 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001258 return FALSE;
1259 }
1260
Chris Allegretta271e9722000-11-10 18:15:43 +00001261 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001262
Chris Allegretta271e9722000-11-10 18:15:43 +00001263 if ( (pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001264
Chris Allegretta271e9722000-11-10 18:15:43 +00001265 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001266 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001267 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001268
Chris Allegretta271e9722000-11-10 18:15:43 +00001269 read_buff = nmalloc( pipe_buff_size + 1 );
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001270
Chris Allegretta271e9722000-11-10 18:15:43 +00001271 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001272
Chris Allegretta271e9722000-11-10 18:15:43 +00001273 while ( (bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001274
Chris Allegretta271e9722000-11-10 18:15:43 +00001275 read_buff[bytesread] = (char) NULL;
1276 read_buff_word = read_buff_ptr = read_buff;
1277
1278 while (*read_buff_ptr != (char) NULL) {
1279
1280 /* Windows version may need to process additional char '\r' */
1281
1282 /* Possible problem here if last word not followed by '\n' */
1283
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001284 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001285 *read_buff_ptr = (char) NULL;
1286 if (!do_int_spell_fix(read_buff_word)) {
1287
1288 close(in_fd[0]);
1289 free(read_buff);
1290 replace_abort();
1291
1292 return TRUE;
1293 }
1294 read_buff_word = read_buff_ptr;
1295 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001296 }
1297
1298 read_buff_ptr++;
1299 }
1300 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001301
1302 close(in_fd[0]);
1303 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001304 replace_abort();
1305
Chris Allegretta271e9722000-11-10 18:15:43 +00001306 /* Process end of spell process */
1307
1308 wait(&spell_status);
1309 if (WIFEXITED(spell_status)) {
1310 if (WEXITSTATUS(spell_status) != 0)
1311 return FALSE;
1312 }
1313 else
1314 return FALSE;
1315
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001316 return TRUE;
1317}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001318
1319/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001320int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001321{
Chris Allegretta271e9722000-11-10 18:15:43 +00001322 int alt_spell_status;
1323 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001324 char *ptr;
1325 static int arglen = 3;
1326 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001327
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001328 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001329
Chris Allegrettae434b452001-01-27 19:25:00 +00001330 /* Set up an argument list to pass the execvp function */
1331 if (spellargs == NULL) {
1332 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001333
Chris Allegrettae434b452001-01-27 19:25:00 +00001334 spellargs[0] = strtok(alt_speller, " ");
1335 while ((ptr = strtok(NULL, " ")) != NULL) {
1336 arglen++;
1337 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1338 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001339 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001340 spellargs[arglen - 1] = NULL;
1341 }
1342 spellargs[arglen - 2] = file_name;
1343
1344 /* Start a new process for the alternate speller */
1345 if ( (pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001346
Chris Allegretta271e9722000-11-10 18:15:43 +00001347 /* Start alternate spell program, we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001348 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001349
1350 /* Should not be reached, if alternate speller is found!!! */
1351
1352 exit(1);
1353 }
1354
1355 /* Could not fork?? */
1356
1357 if (pid_spell < 0)
1358 return FALSE;
1359
1360 /* Wait for alternate speller to complete */
1361
1362 wait(&alt_spell_status);
1363 if (WIFEXITED(alt_spell_status)) {
1364 if (WEXITSTATUS(alt_spell_status) != 0)
1365 return FALSE;
1366 }
1367 else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001368 return FALSE;
1369
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001370 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001371 free_filestruct(fileage);
1372 global_init();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001373 open_file(file_name, 0, 1);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001374 edit_update(fileage, CENTER);
Chris Allegretta271e9722000-11-10 18:15:43 +00001375 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001376 set_modified();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001377
1378 return TRUE;
1379}
1380#endif
1381
1382int do_spell(void)
1383{
1384
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001385#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001386 nano_disabled_msg();
1387 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001388#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001389 char *temp;
1390 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001391
Chris Allegretta271e9722000-11-10 18:15:43 +00001392 if ((temp = tempnam(0, "nano.")) == NULL) {
1393 statusbar(_("Could not create a temporary filename: %s"),
1394 strerror(errno));
1395 return 0;
1396 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001397
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001398 if (write_file(temp, 1) == -1) {
1399 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001400 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001401 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001402
Chris Allegretta271e9722000-11-10 18:15:43 +00001403 if (alt_speller)
1404 spell_res = do_alt_speller(temp);
1405 else
1406 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001407
Chris Allegretta271e9722000-11-10 18:15:43 +00001408 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001409
1410 if (spell_res)
1411 statusbar(_("Finished checking spelling"));
1412 else
1413 statusbar(_("Spell checking failed"));
1414
1415 return spell_res;
1416
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001417#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001418}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001419
1420int do_exit(void)
1421{
1422 int i;
1423
1424 if (!ISSET(MODIFIED))
1425 finish(0);
1426
Chris Allegretta30885552000-07-14 01:20:12 +00001427 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001428 i = 1;
1429 } else {
1430 i =
1431 do_yesno(0, 0,
1432 _
1433 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1434 }
1435
1436#ifdef DEBUG
1437 dump_buffer(fileage);
1438#endif
1439
1440 if (i == 1) {
Chris Allegrettae1ebaf32001-01-07 05:50:36 +00001441 if (do_writeout(filename, 1) > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001442 finish(0);
1443 } else if (i == 0)
1444 finish(0);
1445 else
1446 statusbar(_("Cancelled"));
1447
1448 display_main_list();
1449 return 1;
1450}
1451
1452#ifndef NANO_SMALL
1453#ifdef NCURSES_MOUSE_VERSION
1454void do_mouse(void)
1455{
1456 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001457 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001458
1459 if (getmouse(&mevent) == ERR)
1460 return;
1461
1462 /* If mouse not in edit window, return (add help selection later). */
1463 if (!wenclose(edit, mevent.y, mevent.x))
1464 return;
1465
1466 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1467 mevent.y -= 2;
1468
1469 /* Selecting where the cursor is sets the mark.
1470 * Selecting beyond the line length with the cursor at the end of the
1471 * line sets the mark as well.
1472 */
1473 if ((mevent.y == current_y) &&
1474 ((mevent.x == current_x) || (current_x == strlen(current->data)
1475 && (mevent.x >
1476 strlen(current->data))))) {
1477 if (ISSET(VIEW_MODE)) {
1478 print_view_warning();
1479 return;
1480 }
1481 do_mark();
1482 } else if (mevent.y > current_y) {
1483 while (mevent.y > current_y) {
1484 if (current->next != NULL)
1485 current = current->next;
1486 else
1487 break;
1488 current_y++;
1489 }
1490 } else if (mevent.y < current_y) {
1491 while (mevent.y < current_y) {
1492 if (current->prev != NULL)
1493 current = current->prev;
1494 else
1495 break;
1496 current_y--;
1497 }
1498 }
1499 current_x = mevent.x;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001500 placewewant = current_x;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001501 while (foo < current_x) {
1502 if (current->data[foo] == NANO_CONTROL_I) {
Chris Allegrettae10debd2000-08-22 01:26:42 +00001503 current_x -= tabsize - (foo % tabsize);
1504 tab_found = 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001505 } else if (current->data[foo] & 0x80);
1506 else if (current->data[foo] < 32)
Chris Allegrettae10debd2000-08-22 01:26:42 +00001507 current_x--;
1508 foo++;
1509 }
1510 /* This is where tab_found comes in. I can't figure out why,
1511 * but without it any line with a tab will place the cursor
1512 * one character behind. Whatever, this fixes it. */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001513 if (tab_found == 1)
Chris Allegrettae10debd2000-08-22 01:26:42 +00001514 current_x++;
1515
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001516 if (current_x > strlen(current->data))
1517 current_x = strlen(current->data);
1518
1519 update_cursor();
1520 edit_refresh();
1521
1522}
1523#endif
1524#endif
1525
1526/* Handler for SIGHUP */
1527RETSIGTYPE handle_hup(int signal)
1528{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001529 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001530}
1531
Chris Allegretta18f8be02000-09-04 03:20:38 +00001532/* What do we do when we catch the suspend signal */
1533RETSIGTYPE do_suspend(int signal)
1534{
1535
1536 act.sa_handler = SIG_DFL;
1537 sigemptyset(&act.sa_mask);
1538 sigaction(SIGTSTP, &act, NULL);
1539
1540 endwin();
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001541 fprintf(stderr, "\n\n\n\n\nUse \"fg\" to return to nano\n");
Chris Allegretta18f8be02000-09-04 03:20:38 +00001542 raise(SIGTSTP);
1543}
1544
1545/* Restore the suspend handler when we come back into the prog */
1546RETSIGTYPE do_cont(int signal)
1547{
1548
1549 act.sa_handler = do_suspend;
1550 sigemptyset(&act.sa_mask);
1551 sigaction(SIGTSTP, &act, NULL);
1552 initscr();
1553 total_refresh();
1554}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001555
1556void handle_sigwinch(int s)
1557{
1558#ifndef NANO_SMALL
1559 char *tty = NULL;
1560 int fd = 0;
1561 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001562 struct winsize win;
1563
1564 tty = ttyname(0);
1565 if (!tty)
1566 return;
1567 fd = open(tty, O_RDWR);
1568 if (fd == -1)
1569 return;
1570 result = ioctl(fd, TIOCGWINSZ, &win);
1571 if (result == -1)
1572 return;
1573
1574
1575 COLS = win.ws_col;
1576 LINES = win.ws_row;
1577
Chris Allegrettae61e8302001-01-14 05:18:27 +00001578 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1579 die_too_small();
1580
1581 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1582 die_too_small();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001583
Chris Allegretta0a06e072001-01-23 02:35:04 +00001584 hblank = nrealloc(hblank, COLS + 1);
1585 memset(hblank, ' ', COLS);
1586 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001587
1588#ifdef HAVE_NCURSES_H
1589 resizeterm(LINES, COLS);
1590#ifdef HAVE_WRESIZE
1591 if (wresize(topwin, 2, COLS) == ERR)
1592 die(_("Cannot resize top win"));
1593 if (mvwin(topwin, 0, 0) == ERR)
1594 die(_("Cannot move top win"));
1595 if (wresize(edit, editwinrows, COLS) == ERR)
1596 die(_("Cannot resize edit win"));
1597 if (mvwin(edit, 2, 0) == ERR)
1598 die(_("Cannot move edit win"));
1599 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1600 die(_("Cannot resize bottom win"));
1601 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1602 die(_("Cannot move bottom win"));
1603#endif /* HAVE_WRESIZE */
1604#endif /* HAVE_NCURSES_H */
1605
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001606 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001607
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001608 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001609 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001610 }
1611 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001612
1613 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001614 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001615 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00001616 edit_refresh();
1617 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00001618 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001619 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00001620
Chris Allegretta4e90c402001-01-29 23:40:43 +00001621 /* Turn cursor back on for sure */
1622 curs_set(1);
1623
Chris Allegretta08020882001-01-29 23:37:54 +00001624 /* Jump back to mainloop */
1625 siglongjmp(jmpbuf, 1);
1626
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001627#endif
1628}
1629
Chris Allegretta756f2202000-09-01 13:32:47 +00001630void signal_init(void)
1631{
Chris Allegretta756f2202000-09-01 13:32:47 +00001632
1633 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
1634 memset(&act, 0, sizeof(struct sigaction));
1635 act.sa_handler = SIG_IGN;
1636 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00001637
Chris Allegretta18f8be02000-09-04 03:20:38 +00001638 if (!ISSET(SUSPEND)) {
Chris Allegretta756f2202000-09-01 13:32:47 +00001639 sigaction(SIGTSTP, &act, NULL);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001640 } else {
Chris Allegretta18f8be02000-09-04 03:20:38 +00001641 act.sa_handler = do_suspend;
1642 sigaction(SIGTSTP, &act, NULL);
1643
1644 act.sa_handler = do_cont;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001645 sigaction(SIGCONT, &act, NULL);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001646 }
1647
Chris Allegretta756f2202000-09-01 13:32:47 +00001648
1649 /* Trap SIGHUP cuz we want to write the file out. */
1650 act.sa_handler = handle_hup;
1651 sigaction(SIGHUP, &act, NULL);
1652
1653 act.sa_handler = handle_sigwinch;
1654 sigaction(SIGWINCH, &act, NULL);
1655
1656}
1657
Chris Allegretta2a42af12000-09-12 23:02:49 +00001658void window_init(void)
1659{
Chris Allegrettae61e8302001-01-14 05:18:27 +00001660 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1661 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00001662
Chris Allegretta2a42af12000-09-12 23:02:49 +00001663 /* Setup up the main text window */
1664 edit = newwin(editwinrows, COLS, 2, 0);
1665
1666 /* And the other windows */
1667 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001668 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001669
Chris Allegretta155d6202001-01-08 01:50:37 +00001670#ifdef PDCURSES
1671 /* Oops, I guess we need this again.
1672 Moved here so the keypad still works after a Meta-X, for example */
1673 keypad(edit, TRUE);
1674 keypad(bottomwin, TRUE);
1675#endif
1676
Chris Allegretta2a42af12000-09-12 23:02:49 +00001677}
1678
Chris Allegretta756f2202000-09-01 13:32:47 +00001679void mouse_init(void)
1680{
1681#ifndef NANO_SMALL
1682#ifdef NCURSES_MOUSE_VERSION
1683 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001684 keypad_on(edit, 1);
1685
Chris Allegretta756f2202000-09-01 13:32:47 +00001686 mousemask(BUTTON1_RELEASED, NULL);
1687 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00001688
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001689 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00001690 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001691
Chris Allegretta756f2202000-09-01 13:32:47 +00001692#endif
1693#endif
1694
1695}
1696
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001697int do_tab(void)
1698{
1699 do_char('\t');
1700 return 1;
1701}
1702
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001703#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001704int empty_line(const char *data)
1705{
1706 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001707 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001708 return 0;
1709
1710 data++;
1711 }
1712
1713 return 1;
1714}
1715
1716int no_spaces(const char *data)
1717{
1718 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001719 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001720 return 0;
1721
1722 data++;
1723 }
1724
1725 return 1;
1726}
1727
1728void justify_format(char *data)
1729{
1730 int i = 0;
1731 int len = strlen(data);
1732
1733 /* Skip first character regardless and leading whitespace. */
1734 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001735 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001736 break;
1737 }
1738
1739 i++; /* (i) is now at least 2. */
1740
1741 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
1742 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001743 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001744 && (data[i - 2] != '.')) {
1745 memmove(data + i, data + i + 1, len - i);
1746 len--;
1747 i--;
1748 }
1749 }
1750}
1751#endif
1752
1753int do_justify(void)
1754{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001755#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00001756 nano_disabled_msg();
1757 return 1;
1758#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001759 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00001760 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00001761 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001762
1763 if (empty_line(current->data)) {
1764 /* Justify starting at first non-empty line. */
1765 do {
1766 if (!current->next)
1767 return 1;
1768
1769 current = current->next;
1770 current_y++;
1771 }
1772 while (empty_line(current->data));
1773 } else {
1774 /* Search back for the beginning of the paragraph, where
1775 * Paragraph is 1) A line with leading whitespace
1776 * or 2) A line following an empty line.
1777 */
1778 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001779 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001780 break;
1781
1782 current = current->prev;
1783 current_y--;
1784 }
1785
1786 /* First line with leading whitespace may be empty. */
1787 if (empty_line(current->data)) {
1788 if (current->next) {
1789 current = current->next;
1790 current_y++;
1791 } else
1792 return 1;
1793 }
1794 }
1795 initial = current;
1796 initial_y = current_y;
1797
1798 set_modified();
Chris Allegretta9149e612000-11-27 00:23:41 +00001799 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00001800 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00001801 cutbuffer = NULL;
1802
1803 tmptop = current;
1804 tmpjust = copy_node(current);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001805
1806 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00001807 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001808
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001809 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001810 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001811 && current->next->data[0]) {
1812 filestruct *tmpnode = current->next;
1813 int len = strlen(current->data);
1814 int len2 = strlen(current->next->data);
1815
Chris Allegretta9149e612000-11-27 00:23:41 +00001816 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00001817 tmpjust = copy_node(current->next);
1818 add_to_cutbuffer(tmpjust);
1819
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001820 /* Wiping out a newline */
1821 totsize--;
1822
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001823 /* length of both strings plus space between strings and ending \0. */
1824 current->data = nrealloc(current->data, len + len2 + 2);
1825 current->data[len++] = ' ';
1826 current->data[len] = '\0';
1827
1828 strncat(current->data, current->next->data, len2);
1829
1830 unlink_node(tmpnode);
1831 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001832 }
1833
1834 justify_format(current->data);
1835
1836 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001837 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001838
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001839 if ((strlenpt(current->data) > (fill))
1840 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001841 do {
1842 int i = 0;
1843 int len2 = 0;
1844 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001845
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001846 /* Start at fill , unless line isn't that long (but it
1847 * appears at least fill long with tabs.
1848 */
1849 if (slen > fill)
1850 i = fill;
1851 else
1852 i = slen;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001853
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001854 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001855 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001856 ((strlenpt(current->data) - strlen(current->data + i))
1857 <= fill))
1858 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001859 }
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001860
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001861 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001862 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001863
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001864 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001865
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001866 len2 = strlen(current->data + i + 1);
1867 tmpline->data = nmalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001868
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001869 /* Skip the white space in current. */
1870 memcpy(tmpline->data, current->data + i + 1, len2);
1871 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001872
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001873 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001874
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001875 tmpline->prev = current;
1876 tmpline->next = current->next;
1877 if (current->next != NULL)
1878 current->next->prev = tmpline;
1879
1880 current->next = tmpline;
1881 current = tmpline;
1882 slen -= i + 1;
1883 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001884 } while ((strlenpt(current->data) > (fill))
1885 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001886 }
Chris Allegretta9149e612000-11-27 00:23:41 +00001887 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001888
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001889 if (current->next)
1890 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00001891 else
1892 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001893 current_x = 0;
1894 placewewant = 0;
1895
Adam Rogoyski09f97962000-06-20 02:50:33 +00001896 renumber(initial);
1897 totlines = filebot->lineno;
1898
1899 werase(edit);
1900
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001901 if ((current_y < 0) || (current_y >= editwinrows - 1)
1902 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001903 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001904 center_cursor();
1905 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001906 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001907 }
1908
Adam Rogoyski09f97962000-06-20 02:50:33 +00001909 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00001910 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00001911 /* Change the shortcut list to display the unjustify code */
1912 shortcut_init(1);
1913 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00001914 reset_cursor();
1915
Chris Allegretta07798352000-11-27 22:58:23 +00001916 /* Now get a keystroke and see if it's unjustify, if not unget the keytroke
Chris Allegretta9149e612000-11-27 00:23:41 +00001917 and return */
Chris Allegretta00ae5df2001-02-05 18:24:33 +00001918 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta07798352000-11-27 22:58:23 +00001919 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00001920 blank_statusbar_refresh();
1921 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00001922 /* Else restore the justify we just did (ungrateful user!) */
1923 if (tmptop->prev != NULL)
1924 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00001925 else
1926 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00001927 tmpbot->next->prev = tmptop->prev;
1928 current = tmpbot->next;
1929 tmpbot->next = NULL;
1930 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00001931 if (tmptop->prev == NULL)
1932 edit_refresh();
1933
Chris Allegretta17dcb722001-01-20 21:40:07 +00001934 /* Restore totsize from befure justify */
1935 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00001936 free_filestruct(tmptop);
1937 blank_statusbar_refresh();
1938 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00001939 shortcut_init(0);
1940 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00001941 free_filestruct(cutbuffer);
1942 cutbuffer = cutbak;
1943
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001944 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001945#endif
1946}
1947
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001948#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001949void help_init(void)
1950{
1951 int i, sofar = 0;
1952 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegretta220ba692000-12-18 03:40:00 +00001953 char buf[BUFSIZ] = "";
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001954
1955 /* Compute the space needed for the shortcut lists - we add 15 to
1956 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegretta220ba692000-12-18 03:40:00 +00001957 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001958 if (main_list[i].help != NULL)
1959 allocsize += strlen(main_list[i].help) + 15;
1960
Chris Allegretta756f2202000-09-01 13:32:47 +00001961 /* And for the toggle list, we also allocate space for extra text. */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00001962 for (i = 0; i <= TOGGLE_LEN - 1; i++)
Chris Allegretta756f2202000-09-01 13:32:47 +00001963 if (toggles[i].desc != NULL)
1964 allocsize += strlen(toggles[i].desc) + 30;
1965
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001966 allocsize += strlen(help_text_init);
1967
1968 if (help_text != NULL)
1969 free(help_text);
1970
1971 /* Allocate space for the help text */
1972 help_text = nmalloc(allocsize);
1973
1974 /* Now add the text we want */
1975 strcpy(help_text, help_text_init);
1976
1977 /* Now add our shortcut info */
Chris Allegretta220ba692000-12-18 03:40:00 +00001978 for (i = 0; i <= MAIN_LIST_LEN - 1; i++) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001979 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001980
1981 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00001982 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001983 main_list[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001984 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001985 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001986
1987 if (main_list[i].altval > 0)
Chris Allegrettae49f1232000-09-02 07:20:39 +00001988 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001989 main_list[i].altval - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001990 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001991 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001992
Chris Allegretta756f2202000-09-01 13:32:47 +00001993
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001994 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00001995 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001996
Chris Allegretta756f2202000-09-01 13:32:47 +00001997
1998 strcat(help_text, buf);
1999 strcat(help_text, "\n");
2000 }
2001
2002 /* And the toggles... */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00002003 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002004 sofar = snprintf(buf, BUFSIZ,
2005 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00002006
2007 if (toggles[i].desc != NULL)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002008 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
2009 toggles[i].desc);
Chris Allegretta756f2202000-09-01 13:32:47 +00002010
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002011 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002012 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002013 }
2014
2015}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002016#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002017
Chris Allegretta756f2202000-09-01 13:32:47 +00002018void do_toggle(int which)
2019{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002020#ifdef NANO_SMALL
2021 nano_disabled_msg();
2022#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002023 char *enabled = _("enabled");
2024 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002025
Chris Allegretta2a42af12000-09-12 23:02:49 +00002026 if (ISSET(toggles[which].flag))
Chris Allegretta756f2202000-09-01 13:32:47 +00002027 UNSET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002028 else
Chris Allegretta756f2202000-09-01 13:32:47 +00002029 SET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002030
Chris Allegretta756f2202000-09-01 13:32:47 +00002031 switch (toggles[which].val) {
2032 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002033 shortcut_init(0);
Chris Allegretta756f2202000-09-01 13:32:47 +00002034 display_main_list();
2035 break;
2036 case TOGGLE_SUSPEND_KEY:
2037 signal_init();
2038 break;
2039 case TOGGLE_MOUSE_KEY:
2040 mouse_init();
2041 break;
2042 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002043 wclear(bottomwin);
2044 wrefresh(bottomwin);
2045 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002046 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002047 edit_refresh();
2048 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002049 break;
2050 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002051
2052 if (!ISSET(toggles[which].flag)) {
2053 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002054 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002055 statusbar("%s %s", toggles[which].desc, enabled);
2056 else
2057 statusbar("%s %s", toggles[which].desc, disabled);
2058 } else {
2059 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002060 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002061 statusbar("%s %s", toggles[which].desc, disabled);
2062 else
2063 statusbar("%s %s", toggles[which].desc, enabled);
2064 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002065 SET(DISABLE_CURPOS);
2066
2067#endif
2068}
2069
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002070/* If the NumLock key has made the keypad gone awry, print an error
2071 message, hopefully we can address it later. */
2072void print_numlock_warning(void)
2073{
2074 static int didmsg = 0;
2075 if (!didmsg) {
Chris Allegretta40973792001-01-15 20:25:24 +00002076 statusbar(_("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002077 didmsg = 1;
2078 }
2079}
2080
Chris Allegretta1748cd12001-01-13 17:22:54 +00002081/* This function returns the correct keystroke, given the A,B,C or D
2082 input key. This is a common sequence of many terms which send
2083 Esc-O-[A-D] or Esc-[-[A-D]. */
2084int ABCD(int input)
2085{
2086 switch(input)
2087 {
2088 case 'A':
2089 return(KEY_UP);
2090 case 'B':
2091 return(KEY_DOWN);
2092 case 'C':
2093 return(KEY_RIGHT);
2094 case 'D':
2095 return(KEY_LEFT);
2096 default:
2097 return 0;
2098 }
2099}
2100
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002101int main(int argc, char *argv[])
2102{
2103 int optchr;
2104 int kbinput; /* Input from keyboard */
2105 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002106 int keyhandled; /* Have we handled the keystroke yet? */
2107 int i, modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002108 char *argv0;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002109#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002110 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002111#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002112
2113#ifdef HAVE_GETOPT_LONG
2114 int option_index = 0;
2115 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002116#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002117 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002118#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002119 {"version", 0, 0, 'V'},
2120 {"const", 0, 0, 'c'},
2121 {"suspend", 0, 0, 'z'},
2122 {"nowrap", 0, 0, 'w'},
2123 {"nohelp", 0, 0, 'x'},
2124 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002125 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002126#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002127 {"cut", 0, 0, 'k'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002128#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002129 {"autoindent", 0, 0, 'i'},
2130 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002131#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002132 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002133#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002134 {"fill", 1, 0, 'r'},
2135 {"mouse", 0, 0, 'm'},
2136 {"pico", 0, 0, 'p'},
2137 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002138 {"tabsize", 1, 0, 'T'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002139 {0, 0, 0, 0}
2140 };
2141#endif
2142
2143 /* Flag inits... */
2144 SET(FOLLOW_SYMLINKS);
2145
2146#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002147#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002148 setlocale(LC_ALL, "");
2149 bindtextdomain(PACKAGE, LOCALEDIR);
2150 textdomain(PACKAGE);
2151#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002152#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002153
2154#ifdef HAVE_GETOPT_LONG
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002155 while ((optchr = getopt_long(argc, argv, "?T:RVbcefhiklmpr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002156 long_options, &option_index)) != EOF) {
2157#else
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002158 while ((optchr = getopt(argc, argv, "h?T:RVbcefiklmpr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002159#endif
2160
2161 switch (optchr) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002162 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002163 tabsize = atoi(optarg);
2164 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002165 usage(); /* To stop bogus data for tab width */
2166 finish(1);
2167 }
2168 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002169#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002170 case 'R':
2171 SET(USE_REGEXP);
2172 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002173#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002174 case 'V':
2175 version();
2176 exit(0);
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002177 case 'b':
2178 case 'e':
2179 case 'f':
2180 /* Pico compatibility flags */
2181 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002182 case 'c':
2183 SET(CONSTUPDATE);
2184 break;
2185 case 'h':
2186 case '?':
2187 usage();
2188 exit(0);
2189 case 'i':
2190 SET(AUTOINDENT);
2191 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002192#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002193 case 'k':
2194 SET(CUT_TO_END);
2195 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002196#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002197 case 'l':
2198 UNSET(FOLLOW_SYMLINKS);
2199 break;
2200 case 'm':
2201 SET(USE_MOUSE);
2202 break;
2203 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002204 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002205 break;
2206 case 'r':
2207 fill = atoi(optarg);
2208 if (fill <= 0) {
2209 usage(); /* To stop bogus data (like a string) */
2210 finish(1);
2211 }
2212 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002213#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002214 case 's':
2215 alt_speller = nmalloc(strlen(optarg) + 1);
2216 strcpy(alt_speller, optarg);
2217 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002218#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002219 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002220 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002221 break;
2222 case 'v':
2223 SET(VIEW_MODE);
2224 break;
2225 case 'w':
2226 SET(NO_WRAP);
2227 break;
2228 case 'x':
2229 SET(NO_HELP);
2230 break;
2231 case 'z':
2232 SET(SUSPEND);
2233 break;
2234 default:
2235 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002236 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002237 }
2238
2239 }
2240
2241 argv0 = strrchr(argv[0], '/');
2242 if ((argv0 && strstr(argv0, "pico"))
2243 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002244 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002245
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002246 /* See if there's a non-option in argv (first non-option is the
2247 filename, if +LINE is not given) */
2248 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002249 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002250 else {
2251 /* Look for the +line flag... */
2252 if (argv[optind][0] == '+') {
2253 startline = atoi(&argv[optind][1]);
2254 optind++;
2255 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002256 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002257 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002258 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002259
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002260 } else
2261 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002262 }
2263
2264
2265 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002266 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002267
Chris Allegretta9239d742000-09-06 15:19:18 +00002268#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002269 term = oldterm;
2270 term.c_cc[VINTR] = _POSIX_VDISABLE;
2271 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2272 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002273 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002274#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002275
2276 /* now ncurses init stuff... */
2277 initscr();
2278 savetty();
2279 nonl();
2280 cbreak();
2281 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002282
2283 /* Set up some global variables */
2284 global_init();
Chris Allegretta07798352000-11-27 22:58:23 +00002285 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002286#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002287 init_help_msg();
2288 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002289#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002290 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002291
2292#ifdef DEBUG
2293 fprintf(stderr, _("Main: set up windows\n"));
2294#endif
2295
Chris Allegretta2a42af12000-09-12 23:02:49 +00002296 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002297 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002298
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002299#ifdef DEBUG
2300 fprintf(stderr, _("Main: bottom win\n"));
2301#endif
2302 /* Set up up bottom of window */
2303 display_main_list();
2304
2305#ifdef DEBUG
2306 fprintf(stderr, _("Main: open file\n"));
2307#endif
2308
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002309 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00002310
2311 /* Now we check to see if argv[optind] is non-null to determine if
2312 we're dealing with a new file or not, not argc == 1... */
2313 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002314 new_file();
2315 else
2316 open_file(filename, 0, 0);
2317
2318 if (startline > 0)
2319 do_gotoline(startline);
2320 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002321 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002322
Chris Allegretta08020882001-01-29 23:37:54 +00002323 /* return here after a sigwinch */
2324 sigsetjmp(jmpbuf,1);
2325
2326 /* Fix clobber-age */
2327 kbinput = 0;
2328 keyhandled = 0;
2329 modify_control_seq = 0;
2330
Robert Siemborski6967eec2000-07-08 14:23:32 +00002331 edit_refresh();
2332 reset_cursor();
2333
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002334 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00002335
2336#ifndef _POSIX_VDISABLE
2337 /* We're going to have to do it the old way, i.e. on cygwin */
2338 raw();
2339#endif
2340
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002341 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002342#ifdef DEBUG
2343 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
2344#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002345 if (kbinput == 27) { /* Grab Alt-key stuff first */
2346 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002347 /* Alt-O, suddenly very important ;) */
Chris Allegretta16e41682000-09-11 22:33:54 +00002348 case 79:
2349 kbinput = wgetch(edit);
Chris Allegretta1748cd12001-01-13 17:22:54 +00002350 if (kbinput <= 'D' && kbinput >= 'A')
2351 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002352 else if (kbinput <= 'z' && kbinput >= 'j')
2353 print_numlock_warning();
2354 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002355 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002356#ifdef DEBUG
2357 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002358 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2359 kbinput, kbinput);
2360 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002361 }
2362#endif
2363 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002364 case 27:
2365 /* If we get Alt-Alt, the next keystroke should be the same as a
2366 control sequence */
2367 modify_control_seq = 1;
2368 keyhandled = 1;
2369 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002370 case 91:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002371 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002372 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00002373 kbinput = wgetch(edit);
2374 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002375 kbinput = KEY_F(kbinput - 48);
2376 wgetch(edit);
2377 } else if (kbinput >= '7' && kbinput <= '9') {
2378 kbinput = KEY_F(kbinput - 49);
2379 wgetch(edit);
2380 } else if (kbinput == 126)
2381 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00002382
2383#ifdef DEBUG
2384 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002385 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
2386 kbinput, kbinput);
2387 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002388 }
2389#endif
2390
2391 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002392 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00002393 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00002394 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002395 case '0':
2396 kbinput = KEY_F(9);
2397 wgetch(edit);
2398 break;
2399 case '1':
2400 kbinput = KEY_F(10);
2401 wgetch(edit);
2402 break;
2403 case '3':
2404 kbinput = KEY_F(11);
2405 wgetch(edit);
2406 break;
2407 case '4':
2408 kbinput = KEY_F(12);
2409 wgetch(edit);
2410 break;
2411 case 126: /* Hack, make insert key do something
2412 usefile, like insert file */
2413 do_insertfile();
2414 keyhandled = 1;
2415 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002416#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002417 default:
2418 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
2419 kbinput, kbinput);
2420 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002421#endif
2422
2423 }
2424 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002425 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002426 kbinput = NANO_DELETE_KEY;
2427 wgetch(edit);
2428 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002429 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002430 kbinput = NANO_END_KEY;
2431 wgetch(edit);
2432 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002433 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00002434 kbinput = KEY_PPAGE;
2435 wgetch(edit);
2436 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002437 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00002438 kbinput = KEY_NPAGE;
2439 wgetch(edit);
2440 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002441 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00002442 kbinput = wgetch(edit);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002443 if (kbinput >= 'A' && kbinput <= 'E')
2444 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00002445 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002446 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002447 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002448 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002449 case 'D':
Chris Allegretta1748cd12001-01-13 17:22:54 +00002450 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002451 break;
2452 case 'H':
2453 kbinput = KEY_HOME;
2454 break;
2455 case 'F':
2456 kbinput = KEY_END;
2457 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002458 default:
2459#ifdef DEBUG
2460 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
2461 kbinput, kbinput);
2462#endif
2463 break;
2464 }
2465 break;
2466 default:
2467
2468 /* Check for the altkey defs.... */
2469 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
2470 if (kbinput == main_list[i].altval ||
2471 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002472 kbinput = main_list[i].val;
2473 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002474 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002475#ifndef NANO_SMALL
2476 /* And for toggle switches */
2477 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
2478 if (kbinput == toggles[i].val ||
2479 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002480 do_toggle(i);
2481 keyhandled = 1;
2482 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002483 }
2484#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002485#ifdef DEBUG
2486 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
2487 kbinput);
2488#endif
2489 break;
2490 }
2491 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002492 /* If the modify_control_seq is set, we received an Alt-Alt
2493 sequence before this, so we make this key a control sequence
2494 by subtracting 64 or 96, depending on its value. */
2495 if (!keyhandled && modify_control_seq) {
2496 if (kbinput >= 'A' && kbinput < 'a')
2497 kbinput -= 64;
2498 else if (kbinput >= 'a' && kbinput <= 'z')
2499 kbinput -= 96;
2500
2501 modify_control_seq = 0;
2502 }
2503
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002504 /* Look through the main shortcut list to see if we've hit a
2505 shortcut key */
Chris Allegretta756f2202000-09-01 13:32:47 +00002506 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002507 if (kbinput == main_list[i].val ||
2508 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
2509 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
2510 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
2511 print_view_warning();
2512 else
2513 main_list[i].func();
2514 keyhandled = 1;
2515 }
2516 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002517 /* If we're in raw mode or using Alt-Alt-x, we have to catch
2518 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00002519 if (kbinput == 17 || kbinput == 19)
2520 keyhandled = 1;
2521
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002522 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00002523 if (kbinput == 26) {
2524 if (ISSET(SUSPEND))
2525 do_suspend(0);
2526 keyhandled = 1;
2527 }
Chris Allegretta9239d742000-09-06 15:19:18 +00002528
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002529 /* Last gasp, stuff that's not in the main lists */
2530 if (!keyhandled)
2531 switch (kbinput) {
2532#ifndef NANO_SMALL
2533#ifdef NCURSES_MOUSE_VERSION
2534 case KEY_MOUSE:
2535 do_mouse();
2536 break;
2537#endif
2538#endif
2539 case 0: /* Erg */
2540 do_next_word();
2541 break;
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00002542
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002543 case 331: /* Stuff that we don't want to do squat */
2544 case -1:
2545 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002546#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002547 case 541: /* ???? */
2548 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00002549 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002550 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00002551 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002552#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002553
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002554 break;
2555 default:
2556#ifdef DEBUG
2557 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
2558#endif
2559 /* We no longer stop unhandled sequences so that people with
2560 odd character sets can type... */
2561
2562 if (ISSET(VIEW_MODE)) {
2563 print_view_warning();
2564 break;
2565 }
2566 do_char(kbinput);
2567 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002568 if (ISSET(CONSTUPDATE)) {
2569 if (ISSET(DISABLE_CURPOS))
2570 UNSET(DISABLE_CURPOS);
2571 else
2572 do_cursorpos();
2573 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002574
2575 reset_cursor();
2576 wrefresh(edit);
2577 keyhandled = 0;
2578 }
2579
2580 getchar();
2581 finish(0);
2582
2583}