blob: 9e010072bb6afe2ce08760f857330c3588e31e8a [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * nano.c *
4 * *
5 * Copyright (C) 1999 Chris Allegretta *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 1, or (at your option) *
9 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <stdarg.h>
25#include <signal.h>
26#include <unistd.h>
27#include <string.h>
28#include <fcntl.h>
29#include <sys/stat.h>
30#include <sys/ioctl.h>
31#include <sys/param.h>
Chris Allegretta27eb13f2000-11-05 16:52:21 +000032#include <sys/types.h>
33#include <sys/wait.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000034#include <errno.h>
35#include <ctype.h>
36#include <locale.h>
37#include <limits.h>
Adam Rogoyski77f36de2000-06-07 03:56:54 +000038#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000039
40#include "config.h"
41#include "proto.h"
42#include "nano.h"
43
44#ifndef NANO_SMALL
45#include <libintl.h>
46#define _(string) gettext(string)
47#else
48#define _(string) (string)
49#endif
50
51#ifdef HAVE_TERMIOS_H
52#include <termios.h>
53#endif
54
55#ifdef HAVE_TERMIO_H
56#include <termio.h>
57#endif
58
59#ifdef HAVE_GETOPT_H
60#include <getopt.h>
61#endif
62
63/* Former globals, now static */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000064int fill = 0; /* Fill - where to wrap lines, basically */
65static char *alt_speller; /* Alternative spell command */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000066struct termios oldterm; /* The user's original term settings */
Chris Allegretta18f8be02000-09-04 03:20:38 +000067static struct sigaction act; /* For all out fun signal handlers */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000068
Chris Allegretta65121632000-12-18 07:05:27 +000069#if !defined(NANO_SMALL) && !defined(DISABLE_HELP)
70static char *help_text_init = ""; /* Initial message, not including shortcuts */
71#endif
72
Chris Allegretta27eb13f2000-11-05 16:52:21 +000073char *last_search = NULL; /* Last string we searched for */
74char *last_replace = NULL; /* Last replacement string */
75int search_last_line; /* Is this the last search line? */
76
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +000077void keypad_on(int yesno)
78{
79 keypad(edit, yesno);
80 keypad(bottomwin, yesno);
81}
82
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000083/* What we do when we're all set to exit */
84RETSIGTYPE finish(int sigage)
85{
86 if (!ISSET(NO_HELP)) {
87 mvwaddstr(bottomwin, 1, 0, hblank);
88 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000089 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000090 mvwaddstr(bottomwin, 0, 0, hblank);
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +000091
92 /* Apparently you REALLY can't get away with not calling keypad()
93 or your window looks awful when it exits. so we just call it right
94 before we exit, muhaha :-) */
95 keypad_on(TRUE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000096 wrefresh(bottomwin);
97 endwin();
98
99 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000100 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000101
102 exit(sigage);
103}
104
105/* Die (gracefully?) */
106void die(char *msg, ...)
107{
108 va_list ap;
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000109 char *name;
110 int i;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000111
112 va_start(ap, msg);
113 vfprintf(stderr, msg, ap);
114 va_end(ap);
115
116 /* if we can't save we have REAL bad problems,
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000117 * but we might as well TRY. */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000118 if (filename[0] == '\0') {
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000119 name = "nano.save";
120 i = write_file(name, 1);
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000121 } else {
Chris Allegrettae7a58932000-12-02 02:36:22 +0000122
123 char *buf = nmalloc(strlen(filename) + 6);
124 strcpy(buf, filename);
125 strcat(buf, ".save");
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000126 i = write_file(buf, 1);
127 name = buf;
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000128 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000129 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000130 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000131
132 clear();
133 refresh();
134 resetty();
135 endwin();
136
137 fprintf(stderr, msg);
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000138 if (i != -1)
139 fprintf(stderr, _("\nBuffer written to %s\n"), name);
140 else
Chris Allegretta9756d622000-12-03 03:06:45 +0000141 fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000142
143 exit(1); /* We have a problem: exit w/ errorlevel(1) */
144}
145
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000146void print_view_warning(void)
147{
148 statusbar(_("Key illegal in VIEW mode"));
149}
150
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000151void clear_filename(void)
152{
153 if (filename != NULL)
154 free(filename);
155 filename = nmalloc(1);
156 filename[0] = 0;
157}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000158
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000159/* Initialize global variables - no better way for now */
160void global_init(void)
161{
162 int i;
163
164 center_x = COLS / 2;
165 center_y = LINES / 2;
166 current_x = 0;
167 current_y = 0;
168 editwinrows = LINES - 5 + no_help();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000169 fileage = NULL;
170 cutbuffer = NULL;
171 current = NULL;
172 edittop = NULL;
173 editbot = NULL;
174 totlines = 0;
175 placewewant = 0;
176 if (!fill)
177 fill = COLS - 8;
178 hblank = nmalloc(COLS + 1);
179
180 /* Thanks BG for this bit... */
181 for (i = 0; i <= COLS - 1; i++)
182 hblank[i] = ' ';
183 hblank[i] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000184}
185
186void init_help_msg(void)
187{
188
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000189#if !defined(NANO_SMALL) && !defined(DISABLE_HELP)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000190
191 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000192 _(" nano help text\n\n "
193 "The nano editor is designed to emulate the functionality and "
194 "ease-of-use of the UW Pico text editor. There are four main "
195 "sections of the editor: The top line shows the program "
196 "version, the current filename being edited, and whether "
197 "or not the file has been modified. Next is the main editor "
198 "window showing the file being edited. The status line is "
199 "the third line from the bottom and shows important messages. "
200 "The bottom two lines show the most commonly used shortcuts "
201 "in the editor.\n\n "
202 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000203 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000204 "with the Control (Ctrl) key. Escape-key sequences are notated "
205 "with the Meta (M) symbol and can be entered using either the "
206 "Esc, Alt or Meta key depending on your keyboard setup. The "
207 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000208 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000209#endif
210
211}
212
213/* Make a copy of a node to a pointer (space will be malloc()ed) */
214filestruct *copy_node(filestruct * src)
215{
216 filestruct *dst;
217
218 dst = nmalloc(sizeof(filestruct));
219 dst->data = nmalloc(strlen(src->data) + 1);
220
221 dst->next = src->next;
222 dst->prev = src->prev;
223
224 strcpy(dst->data, src->data);
225 dst->lineno = src->lineno;
226
227 return dst;
228}
229
230/* Unlink a node from the rest of the struct */
231void unlink_node(filestruct * fileptr)
232{
233 if (fileptr->prev != NULL)
234 fileptr->prev->next = fileptr->next;
235
236 if (fileptr->next != NULL)
237 fileptr->next->prev = fileptr->prev;
238}
239
240void delete_node(filestruct * fileptr)
241{
242 if (fileptr->data != NULL)
243 free(fileptr->data);
244 free(fileptr);
245}
246
247/* Okay, now let's duplicate a whole struct! */
248filestruct *copy_filestruct(filestruct * src)
249{
250 filestruct *dst, *tmp, *head, *prev;
251
252 head = copy_node(src);
253 dst = head; /* Else we barf on copying just one line */
254 head->prev = NULL;
255 tmp = src->next;
256 prev = head;
257
258 while (tmp != NULL) {
259 dst = copy_node(tmp);
260 dst->prev = prev;
261 prev->next = dst;
262
263 prev = dst;
264 tmp = tmp->next;
265 }
266
267 dst->next = NULL;
268 return head;
269}
270
271/* Free() a single node */
272int free_node(filestruct * src)
273{
274 if (src == NULL)
275 return 0;
276
277 if (src->next != NULL)
278 free(src->data);
279 free(src);
280 return 1;
281}
282
283int free_filestruct(filestruct * src)
284{
285 filestruct *fileptr = src;
286
287 if (src == NULL)
288 return 0;
289
290 while (fileptr->next != NULL) {
291 fileptr = fileptr->next;
292 free_node(fileptr->prev);
293
294#ifdef DEBUG
295 fprintf(stderr, _("free_node(): free'd a node, YAY!\n"));
296#endif
297 }
298 free_node(fileptr);
299#ifdef DEBUG
300 fprintf(stderr, _("free_node(): free'd last node.\n"));
301#endif
302
303 return 1;
304}
305
306int renumber_all(void)
307{
308 filestruct *temp;
309 long i = 1;
310
311 for (temp = fileage; temp != NULL; temp = temp->next) {
312 temp->lineno = i++;
313 }
314
315 return 0;
316}
317
318int renumber(filestruct * fileptr)
319{
320 filestruct *temp;
321
322 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
323 renumber_all();
324 return 0;
325 }
326 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000327 if (temp->prev != NULL)
328 temp->lineno = temp->prev->lineno + 1;
329 else
330 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000331 }
332
333 return 0;
334}
335
336/* Fix the memory allocation for a string */
337void align(char **strp)
338{
339 /* There was a serious bug here: the new address was never
340 stored anywhere... */
341
342 *strp = nrealloc(*strp, strlen(*strp) + 1);
343}
344
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000345/* Null a string at a certain index and align it */
346void null_at(char *data, int index)
347{
348 data[index] = 0;
349 align(&data);
350}
351
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000352void usage(void)
353{
354#ifdef HAVE_GETOPT_LONG
355 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
356 printf(_("Option Long option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000357 printf(_
358 (" -T --tabsize=[num] Set width of a tab to num\n"));
Chris Allegretta805c26d2000-09-06 13:39:17 +0000359#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000360 printf(_
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000361 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000362#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000363 printf
364 (_
365 (" -V --version Print version information and exit\n"));
366 printf(_
367 (" -c --const Constantly show cursor position\n"));
368 printf(_
369 (" -h --help Show this message\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000370 printf(_
371 (" -i --autoindent Automatically indent new lines\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000372#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000373 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000374 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000375#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000376 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000377 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000378#ifndef NANO_SMALL
379#ifdef NCURSES_MOUSE_VERSION
380 printf(_(" -m --mouse Enable mouse\n"));
381#endif
382#endif
Chris Allegrettad55655f2000-12-27 03:36:47 +0000383 printf(_
384 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000385 printf
386 (_
387 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
388 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000389 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
390 printf(_
391 (" -t --tempfile Auto save on exit, don't prompt\n"));
392 printf(_
393 (" -v --view View (read only) mode\n"));
394 printf(_
395 (" -w --nowrap Don't wrap long lines\n"));
396 printf(_
397 (" -x --nohelp Don't show help window\n"));
398 printf(_
399 (" -z --suspend Enable suspend\n"));
400 printf(_
401 (" +LINE Start at line number LINE\n"));
402#else
403 printf(_("Usage: nano [option] +LINE <file>\n\n"));
404 printf(_("Option Meaning\n"));
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000405 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000406 printf(_(" -R Use regular expressions for search\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000407 printf(_(" -V Print version information and exit\n"));
408 printf(_(" -c Constantly show cursor position\n"));
409 printf(_(" -h Show this message\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000410 printf(_(" -i Automatically indent new lines\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000411#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +0000412 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000413#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000414 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000415 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000416#ifndef NANO_SMALL
417#ifdef NCURSES_MOUSE_VERSION
418 printf(_(" -m Enable mouse\n"));
419#endif
420#endif
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000421 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000422 printf(_(" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
423 printf(_(" -s [prog] Enable alternate speller\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000424 printf(_(" -t Auto save on exit, don't prompt\n"));
425 printf(_(" -v View (read only) mode\n"));
426 printf(_(" -w Don't wrap long lines\n"));
427 printf(_(" -x Don't show help window\n"));
428 printf(_(" -z Enable suspend\n"));
429 printf(_(" +LINE Start at line number LINE\n"));
430#endif
431 exit(0);
432}
433
434void version(void)
435{
436 printf(_(" nano version %s by Chris Allegretta (compiled %s, %s)\n"),
437 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000438 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000439 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000440 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000441
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000442#ifdef NANO_SMALL
443 printf(" --enable-tiny");
444#endif
445#ifdef NANO_EXTRA
446 printf(" --enable-extra");
447#endif
448#ifdef DISABLE_TABCOMP
449 printf(" --disable-tabcomp");
450#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000451#ifdef DISABLE_JUSTIFY
452 printf(" --disable-justify");
453#endif
Chris Allegretta7b36c522000-12-06 01:08:10 +0000454#ifdef DISABLE_SPELLER
455 printf(" --disable-speller");
Chris Allegrettaff269f82000-12-01 18:46:01 +0000456#endif
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000457#ifdef DISABLE_HELP
458 printf(" --disable-help");
459#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000460#ifdef USE_SLANG
461 printf(" --with-slang");
462#endif
463 printf("\n");
464
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000465}
466
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000467filestruct *make_new_node(filestruct * prevnode)
468{
469 filestruct *newnode;
470
471 newnode = nmalloc(sizeof(filestruct));
472 newnode->data = NULL;
473
474 newnode->prev = prevnode;
475 newnode->next = NULL;
476
477 if (prevnode != NULL)
478 newnode->lineno = prevnode->lineno + 1;
479
480 return newnode;
481}
482
Chris Allegretta7975ed82000-07-28 00:58:35 +0000483/* Splice a node into an existing filestruct */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000484void splice_node(filestruct * begin, filestruct * new, filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000485{
486 new->next = end;
487 new->prev = begin;
488 begin->next = new;
489 if (end != NULL)
490 end->prev = new;
491}
492
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000493int do_mark()
494{
495#ifdef NANO_SMALL
496 nano_small_msg();
497#else
498 if (!ISSET(MARK_ISSET)) {
499 statusbar(_("Mark Set"));
500 SET(MARK_ISSET);
501 mark_beginbuf = current;
502 mark_beginx = current_x;
503 } else {
504 statusbar(_("Mark UNset"));
505 UNSET(MARK_ISSET);
506 mark_beginbuf = NULL;
507 mark_beginx = 0;
508
509 edit_refresh();
510 }
511#endif
512 return 1;
513}
514
515int no_help(void)
516{
517 if ISSET
518 (NO_HELP)
519 return 2;
520 else
521 return 0;
522}
523
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000524#ifdef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000525void nano_small_msg(void)
526{
527 statusbar("Sorry, this function not available with nano-tiny option");
528}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000529#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000530
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000531#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000532void nano_disabled_msg(void)
533{
534 statusbar("Sorry, support for this function has been disabled");
535}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000536#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000537
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000538/* The user typed a printable character; add it to the edit buffer */
539void do_char(char ch)
540{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000541 /* magic-line: when a character is inserted on the current magic line,
542 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000543 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000544 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000545 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000546 }
547
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000548 /* More dangerousness fun =) */
549 current->data = nrealloc(current->data, strlen(current->data) + 2);
550 memmove(&current->data[current_x + 1],
551 &current->data[current_x],
552 strlen(current->data) - current_x + 1);
553 current->data[current_x] = ch;
554 do_right();
555
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000556 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000557 check_wrap(current, ch);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000558 set_modified();
559 check_statblank();
560 UNSET(KEEP_CUTBUFFER);
561 totsize++;
562
563}
564
565/* Someone hits return *gasp!* */
566int do_enter(filestruct * inptr)
567{
568 filestruct *new;
569 char *tmp, *spc;
570 int extra = 0;
571
572 new = make_new_node(inptr);
573 tmp = &current->data[current_x];
574 current_x = 0;
575
576 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
577 if (ISSET(AUTOINDENT)) {
578 spc = current->data;
579 if (spc) {
580 while ((*spc == ' ') || (*spc == '\t')) {
581 extra++;
582 spc++;
583 current_x++;
584 }
585 new->data = nmalloc(strlen(tmp) + extra + 1);
586 strncpy(new->data, current->data, extra);
587 strcpy(&new->data[extra], tmp);
588 }
589 } else {
590 new->data = nmalloc(strlen(tmp) + 1);
591 strcpy(new->data, tmp);
592 }
593 *tmp = 0;
594
Chris Allegrettada721be2000-07-31 01:26:42 +0000595 if (inptr->next == NULL) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000596 filebot = new;
597 editbot = new;
598 }
Chris Allegretta7975ed82000-07-28 00:58:35 +0000599 splice_node(inptr, new, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000600
601 totsize++;
602 renumber(current);
603 current = new;
604 align(&current->data);
605
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000606 /* The logic here is as follows:
607 * -> If we are at the bottom of the buffer, we want to recenter
608 * (read: rebuild) the screen and forcably move the cursor.
609 * -> otherwise, we want simply to redraw the screen and update
610 * where we think the cursor is.
611 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000612 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000613 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000614 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000615 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000616 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000617 edit_refresh();
618 update_cursor();
619 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000620
621 totlines++;
622 set_modified();
623
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000624 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000625 return 1;
626}
627
628int do_enter_void(void)
629{
630 return do_enter(current);
631}
632
633void do_next_word(void)
634{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000635 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000636 int i;
637
638 if (current == NULL)
639 return;
640
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000641 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000642 i = current_x;
643 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
644 if (fileptr == current) {
645 while (isalnum((int) fileptr->data[i])
646 && fileptr->data[i] != 0)
647 i++;
648
649 if (fileptr->data[i] == 0) {
650 i = 0;
651 continue;
652 }
653 }
654 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
655 i++;
656
657 if (fileptr->data[i] != 0)
658 break;
659
660 i = 0;
661 }
662 if (fileptr == NULL)
663 current = filebot;
664 else
665 current = fileptr;
666
667 current_x = i;
668 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000669
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000670 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000671 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000672 else {
673 /* If we've jumped lines, refresh the old line. We can't just use
674 * current->prev here, because we may have skipped over some blank
675 * lines, in which case the previous line is the wrong one.
676 */
677 if (current != old)
678 update_line(old, 0);
679
680 update_line(current, current_x);
681 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000682
683}
684
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000685void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000686{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000687 int i = 0; /* Index into ->data for line. */
688 int i_tabs = 0; /* Screen position of ->data[i]. */
689 int last_word_end = -1; /* Location of end of last word found. */
690 int current_word_start = -1; /* Location of start of current word. */
691 int current_word_start_t = -1; /* Location of start of current word screen position. */
692 int current_word_end = -1; /* Location of end of current word */
693 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000694 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000695
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000696 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000697 int right = 0;
698 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000699
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000700 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000701
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000702 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000703 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000704 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000705
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000706 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000707 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000708
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000709 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000710 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000711 i++;
712 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000713 if (inptr->data[i] < 32)
714 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000715 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000716
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000717 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000718 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000719 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000720 } else {
721 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000722 current_word_end_t = i_tabs - 1;
723 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000724 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000725
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000726 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000727 if (i_tabs % tabsize != 0);
728 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000729 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000730
Adam Rogoyski09f97962000-06-20 02:50:33 +0000731 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000732 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000733 }
734
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000735 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000736 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000737 * a) one word takes up the whole line with no starting spaces.
738 * - do nothing and return.
739 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000740 * - word starts new line.
741 * - keep white space on original line up to the cursor.
742 * *) cursor is after word at wrap point
743 * - either it's all white space after word, and this routine isn't called.
744 * - or we are actually in case 2 (2 words).
745 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000746 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000747 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000748 * - white space at end of original line is cleared, unless
749 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000750 * b) cursor is at the word at the wrap point.
751 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000752 * 1. pressed a space and at first character of wrap point word.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000753 * - white space on original line is kept to where cursor was.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000754 * 2. pressed non space (or space elsewhere).
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000755 * - white space at end of original line is cleared.
756 * c) cursor is past the word at the wrap point.
757 * - word at wrap point starts a new line.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000758 * - white space at end of original line is cleared
759 */
760
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000761 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000762
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000763 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000764 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000765 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000766 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000767 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000768 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000769 i++;
770 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000771 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000772 current_word_end = i;
773 break;
774 }
775 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000776
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000777 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000778 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000779 return;
780 }
781 if (current_x >= last_word_end) {
782 right = (current_x - current_word_start) + 1;
783 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000784 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000785 }
786
787 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
788 strcpy(temp->data, &inptr->data[current_word_start]);
789 inptr->data = nrealloc(inptr->data, last_word_end + 2);
790 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000791 } else
792 /* Category 1b: one word on the line and word not taking up whole line
793 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000794 if (last_word_end == -1) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000795 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
796 strcpy(temp->data, &inptr->data[current_word_start]);
797
798 /* Inside word, remove it from original, and move cursor to right spot. */
799 if (current_x >= current_word_start) {
800 right = current_x - current_word_start;
801 current_x = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000802 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000803 }
804
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000805 null_at(inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000806
807 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
808 mark_beginbuf = temp;
809 mark_beginx = 0;
810 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000811 }
812
813 /* Category 2: two or more words on the line. */
814 else {
815
816 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000817 if (current_x < current_word_start) {
818 temp->data =
819 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
820 strcpy(temp->data, &inptr->data[current_word_start]);
821
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000822 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000823 i = current_word_start - 1;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000824 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000825 i--;
826 assert(i >= 0);
827 }
828 } else if (current_x <= last_word_end)
829 i = last_word_end - 1;
830 else
831 i = current_x;
832
833 inptr->data = nrealloc(inptr->data, i + 2);
834 inptr->data[i + 1] = 0;
835 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000836
837
838 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000839 else if ((current_x >= current_word_start)
840 && (current_x <= (current_word_end + 1))) {
841 temp->data =
842 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000843 strcpy(temp->data, &inptr->data[current_word_start]);
844
845 down = 1;
846
847 right = current_x - current_word_start;
848 i = current_word_start - 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000849 if (isspace((int) input_char)
850 && (current_x == current_word_start)) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000851 current_x = current_word_start;
852
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000853 null_at(inptr->data, current_word_start);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000854 } else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000855
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000856 while (isspace((int) inptr->data[i])) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000857 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000858 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000859 }
860 inptr->data = nrealloc(inptr->data, i + 2);
861 inptr->data[i + 1] = 0;
862 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000863 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000864
865
866 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000867 else {
868 temp->data =
869 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000870 strcpy(temp->data, &inptr->data[current_word_start]);
871
872 down = 1;
873 right = current_x - current_word_start;
874
875 current_x = current_word_start;
876 i = current_word_start - 1;
877
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000878 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000879 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000880 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000881 inptr->data = nrealloc(inptr->data, i + 2);
882 inptr->data[i + 1] = 0;
883 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000884 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000885 }
886
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000887 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000888 if (ISSET(SAMELINEWRAP) && inptr->next) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000889 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
890 char *p =
891 nmalloc(strlen(temp->data) + strlen(inptr->next->data) + 2);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000892 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000893
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000894 strcpy(p, temp->data);
895 strcat(p, " ");
896 strcat(p, inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000897
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000898 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000899 inptr->next->data = p;
900
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000901 free(temp->data);
902 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000903
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000904 current_x = old_x;
905 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000906 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000907 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000908 else {
909 temp->prev = inptr;
910 temp->next = inptr->next;
911
912 if (inptr->next)
913 inptr->next->prev = temp;
914 inptr->next = temp;
915
916 if (!temp->next)
917 filebot = temp;
918
919 SET(SAMELINEWRAP);
920 }
921
922
923 totlines++;
Robert Siemborskia417ddc2000-07-24 23:18:48 +0000924 /* Everything about it makes me want this line here but it causes
925 * totsize to be high by one for some reason. Sigh. (Rob) */
926 /* totsize++; */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000927
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000928 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +0000929 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000930
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000931
932 /* Move the cursor to the new line if appropriate. */
933 if (down) {
934 do_right();
935 }
936
937 /* Move the cursor to the correct spot in the line if appropriate. */
938 while (right--) {
939 do_right();
940 }
941
Chris Allegretta234a34d2000-07-29 04:33:38 +0000942 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000943 reset_cursor();
944 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000945}
946
947/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000948void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000949{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000950 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000951#ifdef DEBUG
952 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
953 inptr->data);
954#endif
955
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000956 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000957 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000958 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000959 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000960
961 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000962 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000963
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000964 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +0000965 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000966
Adam Rogoyski09f97962000-06-20 02:50:33 +0000967 if (!inptr->data[i])
968 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000969
Adam Rogoyski09f97962000-06-20 02:50:33 +0000970 /* String must be at least 1 character long. */
971 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000972 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +0000973 if (!char_found)
974 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000975 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000976 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000977 } else
978 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000979 }
Adam Rogoyski09f97962000-06-20 02:50:33 +0000980
981 if (char_found == 2)
982 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000983 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000984}
985
986/* Stuff we do when we abort from programs and want to clean up the
987 * screen. This doesnt do much right now.
988 */
989void do_early_abort(void)
990{
991 blank_statusbar_refresh();
992}
993
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000994int do_backspace(void)
995{
996 filestruct *previous, *tmp;
997
998 if (current_x != 0) {
999 /* Let's get dangerous */
1000 memmove(&current->data[current_x - 1], &current->data[current_x],
1001 strlen(current->data) - current_x + 1);
1002#ifdef DEBUG
1003 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1004#endif
1005 align(&current->data);
1006 do_left();
1007 } else {
1008 if (current == fileage)
1009 return 0; /* Can't delete past top of file */
1010
1011 previous = current->prev;
1012 current_x = strlen(previous->data);
1013 previous->data = nrealloc(previous->data,
1014 strlen(previous->data) +
1015 strlen(current->data) + 1);
1016 strcat(previous->data, current->data);
1017
1018 tmp = current;
1019 unlink_node(current);
1020 delete_node(current);
1021 if (current == edittop) {
1022 if (previous->next)
1023 current = previous->next;
1024 else
1025 current = previous;
Chris Allegrettada721be2000-07-31 01:26:42 +00001026 page_up_center();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001027 } else {
1028 if (previous->next)
1029 current = previous->next;
1030 else
1031 current = previous;
1032 update_line(current, current_x);
1033 }
1034
1035 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001036 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001037 filebot = current;
1038 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001039
1040 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001041 line we're on now is NOT blank. if it is blank we
1042 can just use IT for the magic line. This is how Pico
1043 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001044 if (strcmp(current->data, "")) {
1045 new_magicline();
1046 fix_editbot();
1047 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001048 }
1049
1050 current = previous;
1051 renumber(current);
1052 previous_line();
1053 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001054#ifdef DEBUG
1055 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1056#endif
1057
1058 }
1059
1060 totsize--;
1061 set_modified();
1062 UNSET(KEEP_CUTBUFFER);
1063 edit_refresh();
1064 return 1;
1065}
1066
1067int do_delete(void)
1068{
1069 filestruct *foo;
1070
1071 if (current_x != strlen(current->data)) {
1072 /* Let's get dangerous */
1073 memmove(&current->data[current_x], &current->data[current_x + 1],
1074 strlen(current->data) - current_x);
1075
1076 align(&current->data);
1077
1078 } else if (current->next != NULL) {
1079 current->data = nrealloc(current->data,
1080 strlen(current->data) +
1081 strlen(current->next->data) + 1);
1082 strcat(current->data, current->next->data);
1083
1084 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001085 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001086 filebot = current;
1087 editbot = current;
1088 }
1089
1090 unlink_node(foo);
1091 delete_node(foo);
1092 update_line(current, current_x);
1093
Chris Allegretta28a0f892000-07-05 22:47:54 +00001094 /* Please see the comment in do_basckspace if you don't understand
1095 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001096 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001097 new_magicline();
1098 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001099 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001100 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001101 renumber(current);
1102 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001103 } else
1104 return 0;
1105
1106 totsize--;
1107 set_modified();
1108 UNSET(KEEP_CUTBUFFER);
1109 edit_refresh();
1110 return 1;
1111}
1112
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001113void wrap_reset(void)
1114{
1115 UNSET(SAMELINEWRAP);
1116}
1117
Chris Allegretta7b36c522000-12-06 01:08:10 +00001118#if !defined(NANO_SMALL) && !defined(DISABLE_SPELLER)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001119
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001120int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001121{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001122 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001123 filestruct *begin;
1124 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001125
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001126 /* save where we are */
1127 begin = current;
1128 beginx = current_x + 1;
1129
1130 /* save the current search/replace strings */
1131 search_init_globals();
1132 save_search = mallocstrcpy(save_search, last_search);
1133 save_replace = mallocstrcpy(save_replace, last_replace);
1134
1135 /* set search/replace strings to mis-spelt word */
1136 prevanswer = mallocstrcpy(prevanswer, word);
1137 last_search = mallocstrcpy(last_search, word);
1138 last_replace = mallocstrcpy(last_replace, word);
1139
1140 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001141 current = fileage;
1142 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001143
1144 search_last_line = FALSE;
1145
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001146 edit_update(fileage, TOP);
1147
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001148 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001149 if (findnextstr(TRUE, fileage, beginx_top, prevanswer) != NULL)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001150 {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001151 do_replace_highlight(TRUE, prevanswer);
1152
1153 /* allow replace word to be corrected */
1154 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1155 _("Edit a replacement"));
1156
1157 do_replace_highlight(FALSE, prevanswer);
1158
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001159 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001160 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001161 current_x = beginx_top;
1162
1163 search_last_line = FALSE;
1164
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001165 j = i;
1166 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001167 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001168
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001169 /* restore the search/replace strings */
1170 last_search = mallocstrcpy(last_search, save_search);
1171 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001172
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001173 /* restore where we were */
1174 current = begin;
1175 current_x = beginx - 1;
1176
1177 edit_update(current, CENTER);
1178
1179 if (i == -1)
1180 return FALSE;
1181
1182 return TRUE;
1183}
1184#endif
1185
Chris Allegretta7b36c522000-12-06 01:08:10 +00001186#if !defined(NANO_SMALL) && !defined(DISABLE_SPELLER)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001187
1188/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001189int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001190{
Chris Allegretta271e9722000-11-10 18:15:43 +00001191 char *read_buff, *read_buff_ptr, *read_buff_word;
1192 long pipe_buff_size;
1193 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001194 int spell_status;
1195 pid_t pid_spell;
1196 ssize_t bytesread;
1197
Chris Allegretta271e9722000-11-10 18:15:43 +00001198 /* Create a pipe to spell program */
1199
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001200 if (pipe(in_fd) == -1)
1201 return FALSE;
1202
Chris Allegretta271e9722000-11-10 18:15:43 +00001203 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001204
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001205 if ( (pid_spell = fork()) == 0) {
1206
1207 /* Child continues, (i.e. future spell process) */
1208
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001209 close(in_fd[0]);
1210
Chris Allegretta271e9722000-11-10 18:15:43 +00001211 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001212
Chris Allegretta271e9722000-11-10 18:15:43 +00001213 if ( (tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
1214
1215 close(in_fd[1]);
1216 exit(1);
1217 }
1218
1219 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1220
1221 close(tempfile_fd);
1222 close(in_fd[1]);
1223 exit(1);
1224 }
1225 close(tempfile_fd);
1226
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001227
Chris Allegretta271e9722000-11-10 18:15:43 +00001228 /* send spell's standard out to the pipe */
1229
1230 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1231
1232 close(in_fd[1]);
1233 exit(1);
1234 }
1235 close(in_fd[1]);
1236
1237 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001238 execlp("spell", "spell", NULL);
1239
Chris Allegretta271e9722000-11-10 18:15:43 +00001240 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001241
Chris Allegretta271e9722000-11-10 18:15:43 +00001242 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001243 }
1244
1245 /* Parent continues here */
1246
Chris Allegretta271e9722000-11-10 18:15:43 +00001247 close(in_fd[1]);
1248
1249 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001250
1251 if (pid_spell < 0) {
1252
Chris Allegretta271e9722000-11-10 18:15:43 +00001253 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001254 return FALSE;
1255 }
1256
Chris Allegretta271e9722000-11-10 18:15:43 +00001257 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001258
Chris Allegretta271e9722000-11-10 18:15:43 +00001259 if ( (pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001260
Chris Allegretta271e9722000-11-10 18:15:43 +00001261 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001262 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001263 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001264
Chris Allegretta271e9722000-11-10 18:15:43 +00001265 read_buff = nmalloc( pipe_buff_size + 1 );
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001266
Chris Allegretta271e9722000-11-10 18:15:43 +00001267 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001268
Chris Allegretta271e9722000-11-10 18:15:43 +00001269 while ( (bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001270
Chris Allegretta271e9722000-11-10 18:15:43 +00001271 read_buff[bytesread] = (char) NULL;
1272 read_buff_word = read_buff_ptr = read_buff;
1273
1274 while (*read_buff_ptr != (char) NULL) {
1275
1276 /* Windows version may need to process additional char '\r' */
1277
1278 /* Possible problem here if last word not followed by '\n' */
1279
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001280 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001281 *read_buff_ptr = (char) NULL;
1282 if (!do_int_spell_fix(read_buff_word)) {
1283
1284 close(in_fd[0]);
1285 free(read_buff);
1286 replace_abort();
1287
1288 return TRUE;
1289 }
1290 read_buff_word = read_buff_ptr;
1291 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001292 }
1293
1294 read_buff_ptr++;
1295 }
1296 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001297
1298 close(in_fd[0]);
1299 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001300 replace_abort();
1301
Chris Allegretta271e9722000-11-10 18:15:43 +00001302 /* Process end of spell process */
1303
1304 wait(&spell_status);
1305 if (WIFEXITED(spell_status)) {
1306 if (WEXITSTATUS(spell_status) != 0)
1307 return FALSE;
1308 }
1309 else
1310 return FALSE;
1311
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001312 return TRUE;
1313}
1314#endif
1315
Chris Allegretta7b36c522000-12-06 01:08:10 +00001316#if !defined(NANO_SMALL) && !defined(DISABLE_SPELLER)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001317
1318/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001319int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001320{
Chris Allegretta271e9722000-11-10 18:15:43 +00001321 int alt_spell_status;
1322 pid_t pid_spell;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001323
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001324 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001325
Chris Allegretta271e9722000-11-10 18:15:43 +00001326 /* Start a new process for the alternate speller */
1327
1328 if ( (pid_spell = fork()) == 0) {
1329
1330 /* Start alternate spell program, we are using the PATH here!?!? */
1331 execlp(alt_speller, alt_speller, file_name, NULL);
1332
1333 /* Should not be reached, if alternate speller is found!!! */
1334
1335 exit(1);
1336 }
1337
1338 /* Could not fork?? */
1339
1340 if (pid_spell < 0)
1341 return FALSE;
1342
1343 /* Wait for alternate speller to complete */
1344
1345 wait(&alt_spell_status);
1346 if (WIFEXITED(alt_spell_status)) {
1347 if (WEXITSTATUS(alt_spell_status) != 0)
1348 return FALSE;
1349 }
1350 else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001351 return FALSE;
1352
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001353 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001354 free_filestruct(fileage);
1355 global_init();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001356 open_file(file_name, 0, 1);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001357 edit_update(fileage, CENTER);
Chris Allegretta271e9722000-11-10 18:15:43 +00001358 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001359 set_modified();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001360
1361 return TRUE;
1362}
1363#endif
1364
1365int do_spell(void)
1366{
1367
Chris Allegrettaff269f82000-12-01 18:46:01 +00001368#if defined(NANO_SMALL)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001369 nano_small_msg();
1370 return (TRUE);
Chris Allegretta7b36c522000-12-06 01:08:10 +00001371#elif defined(DISABLE_SPELLER)
Chris Allegrettaff269f82000-12-01 18:46:01 +00001372 nano_disabled_msg();
1373 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001374#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001375 char *temp;
1376 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001377
Chris Allegretta271e9722000-11-10 18:15:43 +00001378 if ((temp = tempnam(0, "nano.")) == NULL) {
1379 statusbar(_("Could not create a temporary filename: %s"),
1380 strerror(errno));
1381 return 0;
1382 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001383
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001384 if (write_file(temp, 1) == -1) {
1385 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001386 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001387 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001388
Chris Allegretta271e9722000-11-10 18:15:43 +00001389 if (alt_speller)
1390 spell_res = do_alt_speller(temp);
1391 else
1392 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001393
Chris Allegretta271e9722000-11-10 18:15:43 +00001394 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001395
1396 if (spell_res)
1397 statusbar(_("Finished checking spelling"));
1398 else
1399 statusbar(_("Spell checking failed"));
1400
1401 return spell_res;
1402
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001403#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001404}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001405
1406int do_exit(void)
1407{
1408 int i;
1409
1410 if (!ISSET(MODIFIED))
1411 finish(0);
1412
Chris Allegretta30885552000-07-14 01:20:12 +00001413 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001414 i = 1;
1415 } else {
1416 i =
1417 do_yesno(0, 0,
1418 _
1419 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1420 }
1421
1422#ifdef DEBUG
1423 dump_buffer(fileage);
1424#endif
1425
1426 if (i == 1) {
1427 if (do_writeout(1) > 0)
1428 finish(0);
1429 } else if (i == 0)
1430 finish(0);
1431 else
1432 statusbar(_("Cancelled"));
1433
1434 display_main_list();
1435 return 1;
1436}
1437
1438#ifndef NANO_SMALL
1439#ifdef NCURSES_MOUSE_VERSION
1440void do_mouse(void)
1441{
1442 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001443 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001444
1445 if (getmouse(&mevent) == ERR)
1446 return;
1447
1448 /* If mouse not in edit window, return (add help selection later). */
1449 if (!wenclose(edit, mevent.y, mevent.x))
1450 return;
1451
1452 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1453 mevent.y -= 2;
1454
1455 /* Selecting where the cursor is sets the mark.
1456 * Selecting beyond the line length with the cursor at the end of the
1457 * line sets the mark as well.
1458 */
1459 if ((mevent.y == current_y) &&
1460 ((mevent.x == current_x) || (current_x == strlen(current->data)
1461 && (mevent.x >
1462 strlen(current->data))))) {
1463 if (ISSET(VIEW_MODE)) {
1464 print_view_warning();
1465 return;
1466 }
1467 do_mark();
1468 } else if (mevent.y > current_y) {
1469 while (mevent.y > current_y) {
1470 if (current->next != NULL)
1471 current = current->next;
1472 else
1473 break;
1474 current_y++;
1475 }
1476 } else if (mevent.y < current_y) {
1477 while (mevent.y < current_y) {
1478 if (current->prev != NULL)
1479 current = current->prev;
1480 else
1481 break;
1482 current_y--;
1483 }
1484 }
1485 current_x = mevent.x;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001486 placewewant = current_x;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001487 while (foo < current_x) {
1488 if (current->data[foo] == NANO_CONTROL_I) {
Chris Allegrettae10debd2000-08-22 01:26:42 +00001489 current_x -= tabsize - (foo % tabsize);
1490 tab_found = 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001491 } else if (current->data[foo] & 0x80);
1492 else if (current->data[foo] < 32)
Chris Allegrettae10debd2000-08-22 01:26:42 +00001493 current_x--;
1494 foo++;
1495 }
1496 /* This is where tab_found comes in. I can't figure out why,
1497 * but without it any line with a tab will place the cursor
1498 * one character behind. Whatever, this fixes it. */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001499 if (tab_found == 1)
Chris Allegrettae10debd2000-08-22 01:26:42 +00001500 current_x++;
1501
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001502 if (current_x > strlen(current->data))
1503 current_x = strlen(current->data);
1504
1505 update_cursor();
1506 edit_refresh();
1507
1508}
1509#endif
1510#endif
1511
1512/* Handler for SIGHUP */
1513RETSIGTYPE handle_hup(int signal)
1514{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001515 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001516}
1517
Chris Allegretta18f8be02000-09-04 03:20:38 +00001518/* What do we do when we catch the suspend signal */
1519RETSIGTYPE do_suspend(int signal)
1520{
1521
1522 act.sa_handler = SIG_DFL;
1523 sigemptyset(&act.sa_mask);
1524 sigaction(SIGTSTP, &act, NULL);
1525
1526 endwin();
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001527 fprintf(stderr, "\n\n\n\n\nUse \"fg\" to return to nano\n");
Chris Allegretta18f8be02000-09-04 03:20:38 +00001528 raise(SIGTSTP);
1529}
1530
1531/* Restore the suspend handler when we come back into the prog */
1532RETSIGTYPE do_cont(int signal)
1533{
1534
1535 act.sa_handler = do_suspend;
1536 sigemptyset(&act.sa_mask);
1537 sigaction(SIGTSTP, &act, NULL);
1538 initscr();
1539 total_refresh();
1540}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001541
1542void handle_sigwinch(int s)
1543{
1544#ifndef NANO_SMALL
1545 char *tty = NULL;
1546 int fd = 0;
1547 int result = 0;
1548 int i = 0;
1549 struct winsize win;
1550
1551 tty = ttyname(0);
1552 if (!tty)
1553 return;
1554 fd = open(tty, O_RDWR);
1555 if (fd == -1)
1556 return;
1557 result = ioctl(fd, TIOCGWINSZ, &win);
1558 if (result == -1)
1559 return;
1560
1561
1562 COLS = win.ws_col;
1563 LINES = win.ws_row;
1564
1565 center_x = COLS / 2;
1566 center_y = LINES / 2;
1567 editwinrows = LINES - 5 + no_help();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001568 fill = COLS - 8;
1569
1570 free(hblank);
1571 hblank = nmalloc(COLS + 1);
1572
1573 for (i = 0; i <= COLS - 1; i++)
1574 hblank[i] = ' ';
1575 hblank[i] = 0;
1576
1577#ifdef HAVE_NCURSES_H
1578 resizeterm(LINES, COLS);
1579#ifdef HAVE_WRESIZE
1580 if (wresize(topwin, 2, COLS) == ERR)
1581 die(_("Cannot resize top win"));
1582 if (mvwin(topwin, 0, 0) == ERR)
1583 die(_("Cannot move top win"));
1584 if (wresize(edit, editwinrows, COLS) == ERR)
1585 die(_("Cannot resize edit win"));
1586 if (mvwin(edit, 2, 0) == ERR)
1587 die(_("Cannot move edit win"));
1588 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1589 die(_("Cannot resize bottom win"));
1590 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1591 die(_("Cannot move bottom win"));
1592#endif /* HAVE_WRESIZE */
1593#endif /* HAVE_NCURSES_H */
1594
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001595 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001596
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001597 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001598 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001599 }
1600 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001601
1602 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001603 refresh();
Chris Allegretta97accc62000-06-19 05:45:52 +00001604 titlebar();
1605 edit_refresh();
1606 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001607 total_refresh();
1608#endif
1609}
1610
Chris Allegretta756f2202000-09-01 13:32:47 +00001611void signal_init(void)
1612{
Chris Allegretta756f2202000-09-01 13:32:47 +00001613
1614 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
1615 memset(&act, 0, sizeof(struct sigaction));
1616 act.sa_handler = SIG_IGN;
1617 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00001618
Chris Allegretta18f8be02000-09-04 03:20:38 +00001619 if (!ISSET(SUSPEND)) {
Chris Allegretta756f2202000-09-01 13:32:47 +00001620 sigaction(SIGTSTP, &act, NULL);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001621 } else {
Chris Allegretta18f8be02000-09-04 03:20:38 +00001622 act.sa_handler = do_suspend;
1623 sigaction(SIGTSTP, &act, NULL);
1624
1625 act.sa_handler = do_cont;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001626 sigaction(SIGCONT, &act, NULL);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001627 }
1628
Chris Allegretta756f2202000-09-01 13:32:47 +00001629
1630 /* Trap SIGHUP cuz we want to write the file out. */
1631 act.sa_handler = handle_hup;
1632 sigaction(SIGHUP, &act, NULL);
1633
1634 act.sa_handler = handle_sigwinch;
1635 sigaction(SIGWINCH, &act, NULL);
1636
1637}
1638
Chris Allegretta2a42af12000-09-12 23:02:49 +00001639void window_init(void)
1640{
Chris Allegretta92c9dd22000-09-13 14:03:27 +00001641 editwinrows = LINES - 5 + no_help();
1642
Chris Allegretta2a42af12000-09-12 23:02:49 +00001643 /* Setup up the main text window */
1644 edit = newwin(editwinrows, COLS, 2, 0);
1645
1646 /* And the other windows */
1647 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001648 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta2a42af12000-09-12 23:02:49 +00001649}
1650
Chris Allegretta756f2202000-09-01 13:32:47 +00001651void mouse_init(void)
1652{
1653#ifndef NANO_SMALL
1654#ifdef NCURSES_MOUSE_VERSION
1655 if (ISSET(USE_MOUSE)) {
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +00001656 keypad_on(TRUE);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00001657
Chris Allegretta756f2202000-09-01 13:32:47 +00001658 mousemask(BUTTON1_RELEASED, NULL);
1659 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00001660
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001661 } else {
Chris Allegretta756f2202000-09-01 13:32:47 +00001662 mousemask(0, NULL);
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +00001663 keypad_on(FALSE);
Chris Allegretta756f2202000-09-01 13:32:47 +00001664 }
1665#endif
1666#endif
1667
1668}
1669
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001670int do_tab(void)
1671{
1672 do_char('\t');
1673 return 1;
1674}
1675
Chris Allegrettaff269f82000-12-01 18:46:01 +00001676#if !defined(NANO_SMALL) && !defined(DISABLE_JUSTIFY)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001677int empty_line(const char *data)
1678{
1679 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001680 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001681 return 0;
1682
1683 data++;
1684 }
1685
1686 return 1;
1687}
1688
1689int no_spaces(const char *data)
1690{
1691 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001692 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001693 return 0;
1694
1695 data++;
1696 }
1697
1698 return 1;
1699}
1700
1701void justify_format(char *data)
1702{
1703 int i = 0;
1704 int len = strlen(data);
1705
1706 /* Skip first character regardless and leading whitespace. */
1707 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001708 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001709 break;
1710 }
1711
1712 i++; /* (i) is now at least 2. */
1713
1714 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
1715 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001716 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001717 && (data[i - 2] != '.')) {
1718 memmove(data + i, data + i + 1, len - i);
1719 len--;
1720 i--;
1721 }
1722 }
1723}
1724#endif
1725
1726int do_justify(void)
1727{
Chris Allegrettaff269f82000-12-01 18:46:01 +00001728#ifdef NANO_SMALL
1729 nano_small_msg();
1730 return 1;
1731#elif defined(DISABLE_JUSTIFY)
1732 nano_disabled_msg();
1733 return 1;
1734#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001735 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta9149e612000-11-27 00:23:41 +00001736 int initial_y, kbinput;
1737 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001738
1739 if (empty_line(current->data)) {
1740 /* Justify starting at first non-empty line. */
1741 do {
1742 if (!current->next)
1743 return 1;
1744
1745 current = current->next;
1746 current_y++;
1747 }
1748 while (empty_line(current->data));
1749 } else {
1750 /* Search back for the beginning of the paragraph, where
1751 * Paragraph is 1) A line with leading whitespace
1752 * or 2) A line following an empty line.
1753 */
1754 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001755 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001756 break;
1757
1758 current = current->prev;
1759 current_y--;
1760 }
1761
1762 /* First line with leading whitespace may be empty. */
1763 if (empty_line(current->data)) {
1764 if (current->next) {
1765 current = current->next;
1766 current_y++;
1767 } else
1768 return 1;
1769 }
1770 }
1771 initial = current;
1772 initial_y = current_y;
1773
1774 set_modified();
Chris Allegretta9149e612000-11-27 00:23:41 +00001775 cutbak = cutbuffer; /* Got to like cutbak ;) */
1776 cutbuffer = NULL;
1777
1778 tmptop = current;
1779 tmpjust = copy_node(current);
1780 add_to_cutbuffer(tmpjust);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001781 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001782 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001783 && current->next->data[0]) {
1784 filestruct *tmpnode = current->next;
1785 int len = strlen(current->data);
1786 int len2 = strlen(current->next->data);
1787
Chris Allegretta9149e612000-11-27 00:23:41 +00001788 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00001789 tmpjust = copy_node(current->next);
1790 add_to_cutbuffer(tmpjust);
1791
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001792 /* length of both strings plus space between strings and ending \0. */
1793 current->data = nrealloc(current->data, len + len2 + 2);
1794 current->data[len++] = ' ';
1795 current->data[len] = '\0';
1796
1797 strncat(current->data, current->next->data, len2);
1798
1799 unlink_node(tmpnode);
1800 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001801 }
1802
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001803 totsize -= strlen(current->data);
1804
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001805 justify_format(current->data);
1806
1807 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001808 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001809
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001810 if ((strlenpt(current->data) > (fill))
1811 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001812 do {
1813 int i = 0;
1814 int len2 = 0;
1815 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001816
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001817 /* Start at fill , unless line isn't that long (but it
1818 * appears at least fill long with tabs.
1819 */
1820 if (slen > fill)
1821 i = fill;
1822 else
1823 i = slen;
1824 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001825 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001826 ((strlenpt(current->data) - strlen(current->data + i))
1827 <= fill))
1828 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001829 }
1830 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001831 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001832
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001833 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001834
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001835 len2 = strlen(current->data + i + 1);
1836 tmpline->data = nmalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001837
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001838 /* Skip the white space in current. */
1839 memcpy(tmpline->data, current->data + i + 1, len2);
1840 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001841
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001842 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001843
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001844 tmpline->prev = current;
1845 tmpline->next = current->next;
1846 if (current->next != NULL)
1847 current->next->prev = tmpline;
1848
1849 current->next = tmpline;
1850 current = tmpline;
1851 slen -= i + 1;
1852 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001853 } while ((strlenpt(current->data) > (fill))
1854 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001855 }
Chris Allegretta9149e612000-11-27 00:23:41 +00001856 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001857
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001858 if (current->next)
1859 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00001860 else
1861 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001862 current_x = 0;
1863 placewewant = 0;
1864
Adam Rogoyski09f97962000-06-20 02:50:33 +00001865 renumber(initial);
1866 totlines = filebot->lineno;
1867
1868 werase(edit);
1869
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001870 if ((current_y < 0) || (current_y >= editwinrows - 1)
1871 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001872 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001873 center_cursor();
1874 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001875 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001876 }
1877
Adam Rogoyski09f97962000-06-20 02:50:33 +00001878 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00001879 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00001880 /* Change the shortcut list to display the unjustify code */
1881 shortcut_init(1);
1882 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00001883 reset_cursor();
1884
Chris Allegretta07798352000-11-27 22:58:23 +00001885 /* Now get a keystroke and see if it's unjustify, if not unget the keytroke
Chris Allegretta9149e612000-11-27 00:23:41 +00001886 and return */
Chris Allegretta4a9c8582000-11-27 22:59:40 +00001887 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY)
Chris Allegretta07798352000-11-27 22:58:23 +00001888 ungetch(kbinput);
Chris Allegretta9149e612000-11-27 00:23:41 +00001889 else {
1890 /* Else restore the justify we just did (ungrateful user!) */
1891 if (tmptop->prev != NULL)
1892 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00001893 else
1894 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00001895 tmpbot->next->prev = tmptop->prev;
1896 current = tmpbot->next;
1897 tmpbot->next = NULL;
1898 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00001899 if (tmptop->prev == NULL)
1900 edit_refresh();
1901
Chris Allegretta9149e612000-11-27 00:23:41 +00001902 free_filestruct(tmptop);
1903 blank_statusbar_refresh();
1904 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00001905 shortcut_init(0);
1906 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00001907 free_filestruct(cutbuffer);
1908 cutbuffer = cutbak;
1909
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001910 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001911#endif
1912}
1913
Chris Allegretta3bc8c722000-12-10 17:03:25 +00001914#if !defined(NANO_SMALL) && !defined(DISABLE_HELP)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001915void help_init(void)
1916{
1917 int i, sofar = 0;
1918 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegretta220ba692000-12-18 03:40:00 +00001919 char buf[BUFSIZ] = "";
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001920
1921 /* Compute the space needed for the shortcut lists - we add 15 to
1922 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegretta220ba692000-12-18 03:40:00 +00001923 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001924 if (main_list[i].help != NULL)
1925 allocsize += strlen(main_list[i].help) + 15;
1926
Chris Allegretta756f2202000-09-01 13:32:47 +00001927 /* And for the toggle list, we also allocate space for extra text. */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00001928 for (i = 0; i <= TOGGLE_LEN - 1; i++)
Chris Allegretta756f2202000-09-01 13:32:47 +00001929 if (toggles[i].desc != NULL)
1930 allocsize += strlen(toggles[i].desc) + 30;
1931
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001932 allocsize += strlen(help_text_init);
1933
1934 if (help_text != NULL)
1935 free(help_text);
1936
1937 /* Allocate space for the help text */
1938 help_text = nmalloc(allocsize);
1939
1940 /* Now add the text we want */
1941 strcpy(help_text, help_text_init);
1942
1943 /* Now add our shortcut info */
Chris Allegretta220ba692000-12-18 03:40:00 +00001944 for (i = 0; i <= MAIN_LIST_LEN - 1; i++) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001945 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001946
1947 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00001948 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001949 main_list[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001950 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001951 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001952
1953 if (main_list[i].altval > 0)
Chris Allegrettae49f1232000-09-02 07:20:39 +00001954 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001955 main_list[i].altval - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001956 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001957 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001958
Chris Allegretta756f2202000-09-01 13:32:47 +00001959
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001960 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00001961 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001962
Chris Allegretta756f2202000-09-01 13:32:47 +00001963
1964 strcat(help_text, buf);
1965 strcat(help_text, "\n");
1966 }
1967
1968 /* And the toggles... */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00001969 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001970 sofar = snprintf(buf, BUFSIZ,
1971 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00001972
1973 if (toggles[i].desc != NULL)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001974 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
1975 toggles[i].desc);
Chris Allegretta756f2202000-09-01 13:32:47 +00001976
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001977 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00001978 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001979 }
1980
1981}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00001982#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001983
Chris Allegretta756f2202000-09-01 13:32:47 +00001984void do_toggle(int which)
1985{
1986#ifndef NANO_SMALL
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00001987 char *enabled = _("enabled");
1988 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00001989
Chris Allegretta2a42af12000-09-12 23:02:49 +00001990 if (ISSET(toggles[which].flag))
Chris Allegretta756f2202000-09-01 13:32:47 +00001991 UNSET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00001992 else
Chris Allegretta756f2202000-09-01 13:32:47 +00001993 SET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00001994
Chris Allegretta756f2202000-09-01 13:32:47 +00001995 switch (toggles[which].val) {
1996 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00001997 shortcut_init(0);
Chris Allegretta756f2202000-09-01 13:32:47 +00001998 display_main_list();
1999 break;
2000 case TOGGLE_SUSPEND_KEY:
2001 signal_init();
2002 break;
2003 case TOGGLE_MOUSE_KEY:
2004 mouse_init();
2005 break;
2006 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002007 wclear(bottomwin);
2008 wrefresh(bottomwin);
2009 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002010 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002011 edit_refresh();
2012 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002013 break;
2014 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002015
2016 if (!ISSET(toggles[which].flag)) {
2017 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002018 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002019 statusbar("%s %s", toggles[which].desc, enabled);
2020 else
2021 statusbar("%s %s", toggles[which].desc, disabled);
2022 } else {
2023 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002024 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002025 statusbar("%s %s", toggles[which].desc, disabled);
2026 else
2027 statusbar("%s %s", toggles[which].desc, enabled);
2028 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002029 SET(DISABLE_CURPOS);
2030
Chris Allegretta4c780be2000-09-01 17:59:18 +00002031#else
2032 nano_small_msg();
Chris Allegretta756f2202000-09-01 13:32:47 +00002033#endif
2034}
2035
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002036int main(int argc, char *argv[])
2037{
2038 int optchr;
2039 int kbinput; /* Input from keyboard */
2040 long startline = 0; /* Line to try and start at */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002041 int keyhandled = 0; /* Have we handled the keystroke yet? */
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002042 int i, modify_control_seq = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002043 char *argv0;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002044#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002045 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002046#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002047
2048#ifdef HAVE_GETOPT_LONG
2049 int option_index = 0;
2050 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002051#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002052 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002053#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002054 {"version", 0, 0, 'V'},
2055 {"const", 0, 0, 'c'},
2056 {"suspend", 0, 0, 'z'},
2057 {"nowrap", 0, 0, 'w'},
2058 {"nohelp", 0, 0, 'x'},
2059 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002060 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002061#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002062 {"cut", 0, 0, 'k'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002063#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002064 {"autoindent", 0, 0, 'i'},
2065 {"tempfile", 0, 0, 't'},
2066 {"speller", 1, 0, 's'},
2067 {"fill", 1, 0, 'r'},
2068 {"mouse", 0, 0, 'm'},
2069 {"pico", 0, 0, 'p'},
2070 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002071 {"tabsize", 1, 0, 'T'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002072 {0, 0, 0, 0}
2073 };
2074#endif
2075
2076 /* Flag inits... */
2077 SET(FOLLOW_SYMLINKS);
2078
2079#ifndef NANO_SMALL
2080 setlocale(LC_ALL, "");
2081 bindtextdomain(PACKAGE, LOCALEDIR);
2082 textdomain(PACKAGE);
2083#endif
2084
2085#ifdef HAVE_GETOPT_LONG
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002086 while ((optchr = getopt_long(argc, argv, "?T:RVbcefhiklmpr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002087 long_options, &option_index)) != EOF) {
2088#else
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002089 while ((optchr = getopt(argc, argv, "h?T:RVbcefiklmpr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002090#endif
2091
2092 switch (optchr) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002093 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002094 tabsize = atoi(optarg);
2095 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002096 usage(); /* To stop bogus data for tab width */
2097 finish(1);
2098 }
2099 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002100#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002101 case 'R':
2102 SET(USE_REGEXP);
2103 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002104#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002105 case 'V':
2106 version();
2107 exit(0);
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002108 case 'b':
2109 case 'e':
2110 case 'f':
2111 /* Pico compatibility flags */
2112 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002113 case 'c':
2114 SET(CONSTUPDATE);
2115 break;
2116 case 'h':
2117 case '?':
2118 usage();
2119 exit(0);
2120 case 'i':
2121 SET(AUTOINDENT);
2122 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002123#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002124 case 'k':
2125 SET(CUT_TO_END);
2126 break;
Chris Allegretta18bd0292000-07-28 01:18:10 +00002127#else
2128 case 'k':
2129 usage(); /* Oops! You dont really have that option */
2130 finish(1);
Chris Allegrettad19e9912000-07-12 18:14:51 +00002131#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002132 case 'l':
2133 UNSET(FOLLOW_SYMLINKS);
2134 break;
2135 case 'm':
2136 SET(USE_MOUSE);
2137 break;
2138 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002139 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002140 break;
2141 case 'r':
2142 fill = atoi(optarg);
2143 if (fill <= 0) {
2144 usage(); /* To stop bogus data (like a string) */
2145 finish(1);
2146 }
2147 break;
2148 case 's':
2149 alt_speller = nmalloc(strlen(optarg) + 1);
2150 strcpy(alt_speller, optarg);
2151 break;
2152 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002153 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002154 break;
2155 case 'v':
2156 SET(VIEW_MODE);
2157 break;
2158 case 'w':
2159 SET(NO_WRAP);
2160 break;
2161 case 'x':
2162 SET(NO_HELP);
2163 break;
2164 case 'z':
2165 SET(SUSPEND);
2166 break;
2167 default:
2168 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002169 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002170 }
2171
2172 }
2173
2174 argv0 = strrchr(argv[0], '/');
2175 if ((argv0 && strstr(argv0, "pico"))
2176 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002177 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002178
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002179 /* See if there's a non-option in argv (first non-option is the
2180 filename, if +LINE is not given) */
2181 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002182 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002183 else {
2184 /* Look for the +line flag... */
2185 if (argv[optind][0] == '+') {
2186 startline = atoi(&argv[optind][1]);
2187 optind++;
2188 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002189 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002190 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002191 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002192
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002193 } else
2194 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002195 }
2196
2197
2198 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002199 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002200
Chris Allegretta9239d742000-09-06 15:19:18 +00002201#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002202 term = oldterm;
2203 term.c_cc[VINTR] = _POSIX_VDISABLE;
2204 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2205 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002206 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002207#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002208
2209 /* now ncurses init stuff... */
2210 initscr();
2211 savetty();
2212 nonl();
2213 cbreak();
2214 noecho();
2215 timeout(0);
2216
2217 /* Set up some global variables */
2218 global_init();
Chris Allegretta07798352000-11-27 22:58:23 +00002219 shortcut_init(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002220 init_help_msg();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002221#if !defined(NANO_SMALL) && !defined(DISABLE_HELP)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002222 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002223#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002224 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002225
2226#ifdef DEBUG
2227 fprintf(stderr, _("Main: set up windows\n"));
2228#endif
2229
Chris Allegretta2a42af12000-09-12 23:02:49 +00002230 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002231 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002232
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002233#ifdef PDCURSES
2234 /* Must have this for the arrow, et al, keys to even work in
2235 PDCurses+cygwin under Windows */
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +00002236 keypad_on(TRUE);
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002237#endif
2238
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002239#ifdef DEBUG
2240 fprintf(stderr, _("Main: bottom win\n"));
2241#endif
2242 /* Set up up bottom of window */
2243 display_main_list();
2244
2245#ifdef DEBUG
2246 fprintf(stderr, _("Main: open file\n"));
2247#endif
2248
2249 titlebar();
Chris Allegretta31c76662000-11-21 06:20:20 +00002250
2251 /* Now we check to see if argv[optind] is non-null to determine if
2252 we're dealing with a new file or not, not argc == 1... */
2253 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002254 new_file();
2255 else
2256 open_file(filename, 0, 0);
2257
2258 if (startline > 0)
2259 do_gotoline(startline);
2260 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002261 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002262
Robert Siemborski6967eec2000-07-08 14:23:32 +00002263 edit_refresh();
2264 reset_cursor();
2265
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002266 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00002267
2268#ifndef _POSIX_VDISABLE
2269 /* We're going to have to do it the old way, i.e. on cygwin */
2270 raw();
2271#endif
2272
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002273 kbinput = wgetch(edit);
2274 if (kbinput == 27) { /* Grab Alt-key stuff first */
2275 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002276 /* Alt-O, suddenly very important ;) */
Chris Allegretta16e41682000-09-11 22:33:54 +00002277 case 79:
2278 kbinput = wgetch(edit);
2279 if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002280 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002281#ifdef DEBUG
2282 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002283 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2284 kbinput, kbinput);
2285 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002286 }
2287#endif
2288 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002289 case 27:
2290 /* If we get Alt-Alt, the next keystroke should be the same as a
2291 control sequence */
2292 modify_control_seq = 1;
2293 keyhandled = 1;
2294 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002295 case 91:
2296
2297 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002298 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00002299 kbinput = wgetch(edit);
2300 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002301 kbinput = KEY_F(kbinput - 48);
2302 wgetch(edit);
2303 } else if (kbinput >= '7' && kbinput <= '9') {
2304 kbinput = KEY_F(kbinput - 49);
2305 wgetch(edit);
2306 } else if (kbinput == 126)
2307 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00002308
2309#ifdef DEBUG
2310 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002311 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
2312 kbinput, kbinput);
2313 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002314 }
2315#endif
2316
2317 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002318 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00002319 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00002320 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002321 case '0':
2322 kbinput = KEY_F(9);
2323 wgetch(edit);
2324 break;
2325 case '1':
2326 kbinput = KEY_F(10);
2327 wgetch(edit);
2328 break;
2329 case '3':
2330 kbinput = KEY_F(11);
2331 wgetch(edit);
2332 break;
2333 case '4':
2334 kbinput = KEY_F(12);
2335 wgetch(edit);
2336 break;
2337 case 126: /* Hack, make insert key do something
2338 usefile, like insert file */
2339 do_insertfile();
2340 keyhandled = 1;
2341 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002342#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002343 default:
2344 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
2345 kbinput, kbinput);
2346 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002347#endif
2348
2349 }
2350 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002351 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002352 kbinput = NANO_DELETE_KEY;
2353 wgetch(edit);
2354 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002355 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002356 kbinput = NANO_END_KEY;
2357 wgetch(edit);
2358 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002359 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00002360 kbinput = KEY_PPAGE;
2361 wgetch(edit);
2362 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002363 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00002364 kbinput = KEY_NPAGE;
2365 wgetch(edit);
2366 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002367 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00002368 kbinput = wgetch(edit);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002369 if (kbinput >= 'A' && kbinput <= 'E')
2370 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00002371 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002372 case 'A':
2373 kbinput = KEY_UP;
2374 break;
2375 case 'B':
2376 kbinput = KEY_DOWN;
2377 break;
2378 case 'C':
2379 kbinput = KEY_RIGHT;
2380 break;
2381 case 'D':
2382 kbinput = KEY_LEFT;
2383 break;
2384 case 'H':
2385 kbinput = KEY_HOME;
2386 break;
2387 case 'F':
2388 kbinput = KEY_END;
2389 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002390 default:
2391#ifdef DEBUG
2392 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
2393 kbinput, kbinput);
2394#endif
2395 break;
2396 }
2397 break;
2398 default:
2399
2400 /* Check for the altkey defs.... */
2401 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
2402 if (kbinput == main_list[i].altval ||
2403 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002404 kbinput = main_list[i].val;
2405 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002406 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002407#ifndef NANO_SMALL
2408 /* And for toggle switches */
2409 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
2410 if (kbinput == toggles[i].val ||
2411 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002412 do_toggle(i);
2413 keyhandled = 1;
2414 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002415 }
2416#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002417#ifdef DEBUG
2418 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
2419 kbinput);
2420#endif
2421 break;
2422 }
2423 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002424 /* If the modify_control_seq is set, we received an Alt-Alt
2425 sequence before this, so we make this key a control sequence
2426 by subtracting 64 or 96, depending on its value. */
2427 if (!keyhandled && modify_control_seq) {
2428 if (kbinput >= 'A' && kbinput < 'a')
2429 kbinput -= 64;
2430 else if (kbinput >= 'a' && kbinput <= 'z')
2431 kbinput -= 96;
2432
2433 modify_control_seq = 0;
2434 }
2435
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002436 /* Look through the main shortcut list to see if we've hit a
2437 shortcut key */
Chris Allegretta756f2202000-09-01 13:32:47 +00002438 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002439 if (kbinput == main_list[i].val ||
2440 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
2441 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
2442 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
2443 print_view_warning();
2444 else
2445 main_list[i].func();
2446 keyhandled = 1;
2447 }
2448 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002449 /* If we're in raw mode or using Alt-Alt-x, we have to catch
2450 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00002451 if (kbinput == 17 || kbinput == 19)
2452 keyhandled = 1;
2453
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002454 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00002455 if (kbinput == 26) {
2456 if (ISSET(SUSPEND))
2457 do_suspend(0);
2458 keyhandled = 1;
2459 }
Chris Allegretta9239d742000-09-06 15:19:18 +00002460
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002461 /* Last gasp, stuff that's not in the main lists */
2462 if (!keyhandled)
2463 switch (kbinput) {
2464#ifndef NANO_SMALL
2465#ifdef NCURSES_MOUSE_VERSION
2466 case KEY_MOUSE:
2467 do_mouse();
2468 break;
2469#endif
2470#endif
2471 case 0: /* Erg */
2472 do_next_word();
2473 break;
2474 case 331: /* Stuff that we don't want to do squat */
2475 case -1:
2476 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002477#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002478 case 541: /* ???? */
2479 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00002480 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002481 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00002482 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002483#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002484
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002485 break;
2486 default:
2487#ifdef DEBUG
2488 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
2489#endif
2490 /* We no longer stop unhandled sequences so that people with
2491 odd character sets can type... */
2492
2493 if (ISSET(VIEW_MODE)) {
2494 print_view_warning();
2495 break;
2496 }
2497 do_char(kbinput);
2498 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002499 if (ISSET(CONSTUPDATE)) {
2500 if (ISSET(DISABLE_CURPOS))
2501 UNSET(DISABLE_CURPOS);
2502 else
2503 do_cursorpos();
2504 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002505
2506 reset_cursor();
2507 wrefresh(edit);
2508 keyhandled = 0;
2509 }
2510
2511 getchar();
2512 finish(0);
2513
2514}