blob: 68e2552ae328cb045abe83880b34ad762196c85a [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 Allegrettad19e9912000-07-12 18:14:51 +0000370#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000371 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000372 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000373#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000374 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000375 (" -i --autoindent Automatically indent new lines\n"));
376 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
383 printf
384 (_
385 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
386 printf(_
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000387 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000388 printf(_
389 (" -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 Allegrettad19e9912000-07-12 18:14:51 +0000410#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +0000411 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000412#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000413 printf(_(" -i Automatically indent new lines\n"));
414 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
421 printf(_
422 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
423 printf(_(" -s [prog] Enable alternate speller\n"));
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000424 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000425 printf(_(" -t Auto save on exit, don't prompt\n"));
426 printf(_(" -v View (read only) mode\n"));
427 printf(_(" -w Don't wrap long lines\n"));
428 printf(_(" -x Don't show help window\n"));
429 printf(_(" -z Enable suspend\n"));
430 printf(_(" +LINE Start at line number LINE\n"));
431#endif
432 exit(0);
433}
434
435void version(void)
436{
437 printf(_(" nano version %s by Chris Allegretta (compiled %s, %s)\n"),
438 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000439 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000440 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000441 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000442
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000443#ifdef NANO_SMALL
444 printf(" --enable-tiny");
445#endif
446#ifdef NANO_EXTRA
447 printf(" --enable-extra");
448#endif
449#ifdef DISABLE_TABCOMP
450 printf(" --disable-tabcomp");
451#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000452#ifdef DISABLE_JUSTIFY
453 printf(" --disable-justify");
454#endif
Chris Allegretta7b36c522000-12-06 01:08:10 +0000455#ifdef DISABLE_SPELLER
456 printf(" --disable-speller");
Chris Allegrettaff269f82000-12-01 18:46:01 +0000457#endif
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000458#ifdef DISABLE_HELP
459 printf(" --disable-help");
460#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000461#ifdef USE_SLANG
462 printf(" --with-slang");
463#endif
464 printf("\n");
465
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000466}
467
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000468filestruct *make_new_node(filestruct * prevnode)
469{
470 filestruct *newnode;
471
472 newnode = nmalloc(sizeof(filestruct));
473 newnode->data = NULL;
474
475 newnode->prev = prevnode;
476 newnode->next = NULL;
477
478 if (prevnode != NULL)
479 newnode->lineno = prevnode->lineno + 1;
480
481 return newnode;
482}
483
Chris Allegretta7975ed82000-07-28 00:58:35 +0000484/* Splice a node into an existing filestruct */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000485void splice_node(filestruct * begin, filestruct * new, filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000486{
487 new->next = end;
488 new->prev = begin;
489 begin->next = new;
490 if (end != NULL)
491 end->prev = new;
492}
493
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000494int do_mark()
495{
496#ifdef NANO_SMALL
497 nano_small_msg();
498#else
499 if (!ISSET(MARK_ISSET)) {
500 statusbar(_("Mark Set"));
501 SET(MARK_ISSET);
502 mark_beginbuf = current;
503 mark_beginx = current_x;
504 } else {
505 statusbar(_("Mark UNset"));
506 UNSET(MARK_ISSET);
507 mark_beginbuf = NULL;
508 mark_beginx = 0;
509
510 edit_refresh();
511 }
512#endif
513 return 1;
514}
515
516int no_help(void)
517{
518 if ISSET
519 (NO_HELP)
520 return 2;
521 else
522 return 0;
523}
524
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000525#ifdef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000526void nano_small_msg(void)
527{
528 statusbar("Sorry, this function not available with nano-tiny option");
529}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000530#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000531
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000532#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000533void nano_disabled_msg(void)
534{
535 statusbar("Sorry, support for this function has been disabled");
536}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000537#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000538
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000539/* The user typed a printable character; add it to the edit buffer */
540void do_char(char ch)
541{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000542 /* magic-line: when a character is inserted on the current magic line,
543 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000544 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000545 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000546 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000547 }
548
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000549 /* More dangerousness fun =) */
550 current->data = nrealloc(current->data, strlen(current->data) + 2);
551 memmove(&current->data[current_x + 1],
552 &current->data[current_x],
553 strlen(current->data) - current_x + 1);
554 current->data[current_x] = ch;
555 do_right();
556
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000557 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000558 check_wrap(current, ch);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000559 set_modified();
560 check_statblank();
561 UNSET(KEEP_CUTBUFFER);
562 totsize++;
563
564}
565
566/* Someone hits return *gasp!* */
567int do_enter(filestruct * inptr)
568{
569 filestruct *new;
570 char *tmp, *spc;
571 int extra = 0;
572
573 new = make_new_node(inptr);
574 tmp = &current->data[current_x];
575 current_x = 0;
576
577 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
578 if (ISSET(AUTOINDENT)) {
579 spc = current->data;
580 if (spc) {
581 while ((*spc == ' ') || (*spc == '\t')) {
582 extra++;
583 spc++;
584 current_x++;
585 }
586 new->data = nmalloc(strlen(tmp) + extra + 1);
587 strncpy(new->data, current->data, extra);
588 strcpy(&new->data[extra], tmp);
589 }
590 } else {
591 new->data = nmalloc(strlen(tmp) + 1);
592 strcpy(new->data, tmp);
593 }
594 *tmp = 0;
595
Chris Allegrettada721be2000-07-31 01:26:42 +0000596 if (inptr->next == NULL) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000597 filebot = new;
598 editbot = new;
599 }
Chris Allegretta7975ed82000-07-28 00:58:35 +0000600 splice_node(inptr, new, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000601
602 totsize++;
603 renumber(current);
604 current = new;
605 align(&current->data);
606
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000607 /* The logic here is as follows:
608 * -> If we are at the bottom of the buffer, we want to recenter
609 * (read: rebuild) the screen and forcably move the cursor.
610 * -> otherwise, we want simply to redraw the screen and update
611 * where we think the cursor is.
612 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000613 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000614 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000615 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000616 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000617 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000618 edit_refresh();
619 update_cursor();
620 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000621
622 totlines++;
623 set_modified();
624
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000625 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000626 return 1;
627}
628
629int do_enter_void(void)
630{
631 return do_enter(current);
632}
633
634void do_next_word(void)
635{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000636 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000637 int i;
638
639 if (current == NULL)
640 return;
641
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000642 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000643 i = current_x;
644 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
645 if (fileptr == current) {
646 while (isalnum((int) fileptr->data[i])
647 && fileptr->data[i] != 0)
648 i++;
649
650 if (fileptr->data[i] == 0) {
651 i = 0;
652 continue;
653 }
654 }
655 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
656 i++;
657
658 if (fileptr->data[i] != 0)
659 break;
660
661 i = 0;
662 }
663 if (fileptr == NULL)
664 current = filebot;
665 else
666 current = fileptr;
667
668 current_x = i;
669 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000670
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000671 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000672 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000673 else {
674 /* If we've jumped lines, refresh the old line. We can't just use
675 * current->prev here, because we may have skipped over some blank
676 * lines, in which case the previous line is the wrong one.
677 */
678 if (current != old)
679 update_line(old, 0);
680
681 update_line(current, current_x);
682 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000683
684}
685
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000686void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000687{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000688 int i = 0; /* Index into ->data for line. */
689 int i_tabs = 0; /* Screen position of ->data[i]. */
690 int last_word_end = -1; /* Location of end of last word found. */
691 int current_word_start = -1; /* Location of start of current word. */
692 int current_word_start_t = -1; /* Location of start of current word screen position. */
693 int current_word_end = -1; /* Location of end of current word */
694 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000695 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000696
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000697 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000698 int right = 0;
699 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000700
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000701 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000702
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000703 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000704 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000705 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000706
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000707 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000708 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000709
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000710 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000711 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000712 i++;
713 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000714 if (inptr->data[i] < 32)
715 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000716 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000717
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000718 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000719 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000720 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000721 } else {
722 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000723 current_word_end_t = i_tabs - 1;
724 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000725 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000726
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000727 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000728 if (i_tabs % tabsize != 0);
729 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000730 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000731
Adam Rogoyski09f97962000-06-20 02:50:33 +0000732 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000733 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000734 }
735
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000736 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000737 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000738 * a) one word takes up the whole line with no starting spaces.
739 * - do nothing and return.
740 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000741 * - word starts new line.
742 * - keep white space on original line up to the cursor.
743 * *) cursor is after word at wrap point
744 * - either it's all white space after word, and this routine isn't called.
745 * - or we are actually in case 2 (2 words).
746 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000747 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000748 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000749 * - white space at end of original line is cleared, unless
750 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000751 * b) cursor is at the word at the wrap point.
752 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000753 * 1. pressed a space and at first character of wrap point word.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000754 * - white space on original line is kept to where cursor was.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000755 * 2. pressed non space (or space elsewhere).
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000756 * - white space at end of original line is cleared.
757 * c) cursor is past the word at the wrap point.
758 * - word at wrap point starts a new line.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000759 * - white space at end of original line is cleared
760 */
761
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000762 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000763
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000764 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000765 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000766 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000767 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000768 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000769 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000770 i++;
771 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000772 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000773 current_word_end = i;
774 break;
775 }
776 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000777
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000778 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000779 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000780 return;
781 }
782 if (current_x >= last_word_end) {
783 right = (current_x - current_word_start) + 1;
784 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000785 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000786 }
787
788 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
789 strcpy(temp->data, &inptr->data[current_word_start]);
790 inptr->data = nrealloc(inptr->data, last_word_end + 2);
791 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000792 } else
793 /* Category 1b: one word on the line and word not taking up whole line
794 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000795 if (last_word_end == -1) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000796 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
797 strcpy(temp->data, &inptr->data[current_word_start]);
798
799 /* Inside word, remove it from original, and move cursor to right spot. */
800 if (current_x >= current_word_start) {
801 right = current_x - current_word_start;
802 current_x = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000803 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000804 }
805
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000806 null_at(inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000807
808 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
809 mark_beginbuf = temp;
810 mark_beginx = 0;
811 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000812 }
813
814 /* Category 2: two or more words on the line. */
815 else {
816
817 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000818 if (current_x < current_word_start) {
819 temp->data =
820 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
821 strcpy(temp->data, &inptr->data[current_word_start]);
822
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000823 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000824 i = current_word_start - 1;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000825 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000826 i--;
827 assert(i >= 0);
828 }
829 } else if (current_x <= last_word_end)
830 i = last_word_end - 1;
831 else
832 i = current_x;
833
834 inptr->data = nrealloc(inptr->data, i + 2);
835 inptr->data[i + 1] = 0;
836 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000837
838
839 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000840 else if ((current_x >= current_word_start)
841 && (current_x <= (current_word_end + 1))) {
842 temp->data =
843 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000844 strcpy(temp->data, &inptr->data[current_word_start]);
845
846 down = 1;
847
848 right = current_x - current_word_start;
849 i = current_word_start - 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000850 if (isspace((int) input_char)
851 && (current_x == current_word_start)) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000852 current_x = current_word_start;
853
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000854 null_at(inptr->data, current_word_start);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000855 } else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000856
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000857 while (isspace((int) inptr->data[i])) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000858 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000859 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000860 }
861 inptr->data = nrealloc(inptr->data, i + 2);
862 inptr->data[i + 1] = 0;
863 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000864 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000865
866
867 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000868 else {
869 temp->data =
870 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000871 strcpy(temp->data, &inptr->data[current_word_start]);
872
873 down = 1;
874 right = current_x - current_word_start;
875
876 current_x = current_word_start;
877 i = current_word_start - 1;
878
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000879 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000880 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000881 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000882 inptr->data = nrealloc(inptr->data, i + 2);
883 inptr->data[i + 1] = 0;
884 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000885 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000886 }
887
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000888 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000889 if (ISSET(SAMELINEWRAP) && inptr->next) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000890 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
891 char *p =
892 nmalloc(strlen(temp->data) + strlen(inptr->next->data) + 2);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000893 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000894
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000895 strcpy(p, temp->data);
896 strcat(p, " ");
897 strcat(p, inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000898
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000899 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000900 inptr->next->data = p;
901
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000902 free(temp->data);
903 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000904
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000905 current_x = old_x;
906 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000907 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000908 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000909 else {
910 temp->prev = inptr;
911 temp->next = inptr->next;
912
913 if (inptr->next)
914 inptr->next->prev = temp;
915 inptr->next = temp;
916
917 if (!temp->next)
918 filebot = temp;
919
920 SET(SAMELINEWRAP);
921 }
922
923
924 totlines++;
Robert Siemborskia417ddc2000-07-24 23:18:48 +0000925 /* Everything about it makes me want this line here but it causes
926 * totsize to be high by one for some reason. Sigh. (Rob) */
927 /* totsize++; */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000928
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000929 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +0000930 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000931
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000932
933 /* Move the cursor to the new line if appropriate. */
934 if (down) {
935 do_right();
936 }
937
938 /* Move the cursor to the correct spot in the line if appropriate. */
939 while (right--) {
940 do_right();
941 }
942
Chris Allegretta234a34d2000-07-29 04:33:38 +0000943 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000944 reset_cursor();
945 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000946}
947
948/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000949void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000950{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000951 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000952#ifdef DEBUG
953 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
954 inptr->data);
955#endif
956
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000957 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000958 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000959 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000960 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000961
962 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000963 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000964
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000965 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +0000966 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000967
Adam Rogoyski09f97962000-06-20 02:50:33 +0000968 if (!inptr->data[i])
969 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000970
Adam Rogoyski09f97962000-06-20 02:50:33 +0000971 /* String must be at least 1 character long. */
972 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000973 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +0000974 if (!char_found)
975 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000976 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000977 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000978 } else
979 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000980 }
Adam Rogoyski09f97962000-06-20 02:50:33 +0000981
982 if (char_found == 2)
983 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000984 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000985}
986
987/* Stuff we do when we abort from programs and want to clean up the
988 * screen. This doesnt do much right now.
989 */
990void do_early_abort(void)
991{
992 blank_statusbar_refresh();
993}
994
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000995int do_backspace(void)
996{
997 filestruct *previous, *tmp;
998
999 if (current_x != 0) {
1000 /* Let's get dangerous */
1001 memmove(&current->data[current_x - 1], &current->data[current_x],
1002 strlen(current->data) - current_x + 1);
1003#ifdef DEBUG
1004 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1005#endif
1006 align(&current->data);
1007 do_left();
1008 } else {
1009 if (current == fileage)
1010 return 0; /* Can't delete past top of file */
1011
1012 previous = current->prev;
1013 current_x = strlen(previous->data);
1014 previous->data = nrealloc(previous->data,
1015 strlen(previous->data) +
1016 strlen(current->data) + 1);
1017 strcat(previous->data, current->data);
1018
1019 tmp = current;
1020 unlink_node(current);
1021 delete_node(current);
1022 if (current == edittop) {
1023 if (previous->next)
1024 current = previous->next;
1025 else
1026 current = previous;
Chris Allegrettada721be2000-07-31 01:26:42 +00001027 page_up_center();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001028 } else {
1029 if (previous->next)
1030 current = previous->next;
1031 else
1032 current = previous;
1033 update_line(current, current_x);
1034 }
1035
1036 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001037 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001038 filebot = current;
1039 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001040
1041 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001042 line we're on now is NOT blank. if it is blank we
1043 can just use IT for the magic line. This is how Pico
1044 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001045 if (strcmp(current->data, "")) {
1046 new_magicline();
1047 fix_editbot();
1048 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001049 }
1050
1051 current = previous;
1052 renumber(current);
1053 previous_line();
1054 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001055#ifdef DEBUG
1056 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1057#endif
1058
1059 }
1060
1061 totsize--;
1062 set_modified();
1063 UNSET(KEEP_CUTBUFFER);
1064 edit_refresh();
1065 return 1;
1066}
1067
1068int do_delete(void)
1069{
1070 filestruct *foo;
1071
1072 if (current_x != strlen(current->data)) {
1073 /* Let's get dangerous */
1074 memmove(&current->data[current_x], &current->data[current_x + 1],
1075 strlen(current->data) - current_x);
1076
1077 align(&current->data);
1078
1079 } else if (current->next != NULL) {
1080 current->data = nrealloc(current->data,
1081 strlen(current->data) +
1082 strlen(current->next->data) + 1);
1083 strcat(current->data, current->next->data);
1084
1085 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001086 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001087 filebot = current;
1088 editbot = current;
1089 }
1090
1091 unlink_node(foo);
1092 delete_node(foo);
1093 update_line(current, current_x);
1094
Chris Allegretta28a0f892000-07-05 22:47:54 +00001095 /* Please see the comment in do_basckspace if you don't understand
1096 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001097 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001098 new_magicline();
1099 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001100 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001101 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001102 renumber(current);
1103 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001104 } else
1105 return 0;
1106
1107 totsize--;
1108 set_modified();
1109 UNSET(KEEP_CUTBUFFER);
1110 edit_refresh();
1111 return 1;
1112}
1113
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001114void wrap_reset(void)
1115{
1116 UNSET(SAMELINEWRAP);
1117}
1118
Chris Allegretta7b36c522000-12-06 01:08:10 +00001119#if !defined(NANO_SMALL) && !defined(DISABLE_SPELLER)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001120
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001121int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001122{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001123 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001124 filestruct *begin;
1125 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001126
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001127 /* save where we are */
1128 begin = current;
1129 beginx = current_x + 1;
1130
1131 /* save the current search/replace strings */
1132 search_init_globals();
1133 save_search = mallocstrcpy(save_search, last_search);
1134 save_replace = mallocstrcpy(save_replace, last_replace);
1135
1136 /* set search/replace strings to mis-spelt word */
1137 prevanswer = mallocstrcpy(prevanswer, word);
1138 last_search = mallocstrcpy(last_search, word);
1139 last_replace = mallocstrcpy(last_replace, word);
1140
1141 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001142 current = fileage;
1143 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001144
1145 search_last_line = FALSE;
1146
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001147 edit_update(fileage, TOP);
1148
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001149 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001150 if (findnextstr(TRUE, fileage, beginx_top, prevanswer) != NULL)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001151 {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001152 do_replace_highlight(TRUE, prevanswer);
1153
1154 /* allow replace word to be corrected */
1155 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1156 _("Edit a replacement"));
1157
1158 do_replace_highlight(FALSE, prevanswer);
1159
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001160 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001161 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001162 current_x = beginx_top;
1163
1164 search_last_line = FALSE;
1165
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001166 j = i;
1167 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001168 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001169
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001170 /* restore the search/replace strings */
1171 last_search = mallocstrcpy(last_search, save_search);
1172 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001173
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001174 /* restore where we were */
1175 current = begin;
1176 current_x = beginx - 1;
1177
1178 edit_update(current, CENTER);
1179
1180 if (i == -1)
1181 return FALSE;
1182
1183 return TRUE;
1184}
1185#endif
1186
Chris Allegretta7b36c522000-12-06 01:08:10 +00001187#if !defined(NANO_SMALL) && !defined(DISABLE_SPELLER)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001188
1189/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001190int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001191{
Chris Allegretta271e9722000-11-10 18:15:43 +00001192 char *read_buff, *read_buff_ptr, *read_buff_word;
1193 long pipe_buff_size;
1194 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001195 int spell_status;
1196 pid_t pid_spell;
1197 ssize_t bytesread;
1198
Chris Allegretta271e9722000-11-10 18:15:43 +00001199 /* Create a pipe to spell program */
1200
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001201 if (pipe(in_fd) == -1)
1202 return FALSE;
1203
Chris Allegretta271e9722000-11-10 18:15:43 +00001204 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001205
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001206 if ( (pid_spell = fork()) == 0) {
1207
1208 /* Child continues, (i.e. future spell process) */
1209
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001210 close(in_fd[0]);
1211
Chris Allegretta271e9722000-11-10 18:15:43 +00001212 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001213
Chris Allegretta271e9722000-11-10 18:15:43 +00001214 if ( (tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
1215
1216 close(in_fd[1]);
1217 exit(1);
1218 }
1219
1220 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1221
1222 close(tempfile_fd);
1223 close(in_fd[1]);
1224 exit(1);
1225 }
1226 close(tempfile_fd);
1227
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001228
Chris Allegretta271e9722000-11-10 18:15:43 +00001229 /* send spell's standard out to the pipe */
1230
1231 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1232
1233 close(in_fd[1]);
1234 exit(1);
1235 }
1236 close(in_fd[1]);
1237
1238 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001239 execlp("spell", "spell", NULL);
1240
Chris Allegretta271e9722000-11-10 18:15:43 +00001241 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001242
Chris Allegretta271e9722000-11-10 18:15:43 +00001243 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001244 }
1245
1246 /* Parent continues here */
1247
Chris Allegretta271e9722000-11-10 18:15:43 +00001248 close(in_fd[1]);
1249
1250 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001251
1252 if (pid_spell < 0) {
1253
Chris Allegretta271e9722000-11-10 18:15:43 +00001254 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001255 return FALSE;
1256 }
1257
Chris Allegretta271e9722000-11-10 18:15:43 +00001258 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001259
Chris Allegretta271e9722000-11-10 18:15:43 +00001260 if ( (pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001261
Chris Allegretta271e9722000-11-10 18:15:43 +00001262 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001263 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001264 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001265
Chris Allegretta271e9722000-11-10 18:15:43 +00001266 read_buff = nmalloc( pipe_buff_size + 1 );
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001267
Chris Allegretta271e9722000-11-10 18:15:43 +00001268 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001269
Chris Allegretta271e9722000-11-10 18:15:43 +00001270 while ( (bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001271
Chris Allegretta271e9722000-11-10 18:15:43 +00001272 read_buff[bytesread] = (char) NULL;
1273 read_buff_word = read_buff_ptr = read_buff;
1274
1275 while (*read_buff_ptr != (char) NULL) {
1276
1277 /* Windows version may need to process additional char '\r' */
1278
1279 /* Possible problem here if last word not followed by '\n' */
1280
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001281 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001282 *read_buff_ptr = (char) NULL;
1283 if (!do_int_spell_fix(read_buff_word)) {
1284
1285 close(in_fd[0]);
1286 free(read_buff);
1287 replace_abort();
1288
1289 return TRUE;
1290 }
1291 read_buff_word = read_buff_ptr;
1292 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001293 }
1294
1295 read_buff_ptr++;
1296 }
1297 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001298
1299 close(in_fd[0]);
1300 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001301 replace_abort();
1302
Chris Allegretta271e9722000-11-10 18:15:43 +00001303 /* Process end of spell process */
1304
1305 wait(&spell_status);
1306 if (WIFEXITED(spell_status)) {
1307 if (WEXITSTATUS(spell_status) != 0)
1308 return FALSE;
1309 }
1310 else
1311 return FALSE;
1312
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001313 return TRUE;
1314}
1315#endif
1316
Chris Allegretta7b36c522000-12-06 01:08:10 +00001317#if !defined(NANO_SMALL) && !defined(DISABLE_SPELLER)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001318
1319/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001320int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001321{
Chris Allegretta271e9722000-11-10 18:15:43 +00001322 int alt_spell_status;
1323 pid_t pid_spell;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001324
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001325 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001326
Chris Allegretta271e9722000-11-10 18:15:43 +00001327 /* Start a new process for the alternate speller */
1328
1329 if ( (pid_spell = fork()) == 0) {
1330
1331 /* Start alternate spell program, we are using the PATH here!?!? */
1332 execlp(alt_speller, alt_speller, file_name, NULL);
1333
1334 /* Should not be reached, if alternate speller is found!!! */
1335
1336 exit(1);
1337 }
1338
1339 /* Could not fork?? */
1340
1341 if (pid_spell < 0)
1342 return FALSE;
1343
1344 /* Wait for alternate speller to complete */
1345
1346 wait(&alt_spell_status);
1347 if (WIFEXITED(alt_spell_status)) {
1348 if (WEXITSTATUS(alt_spell_status) != 0)
1349 return FALSE;
1350 }
1351 else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001352 return FALSE;
1353
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001354 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001355 free_filestruct(fileage);
1356 global_init();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001357 open_file(file_name, 0, 1);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001358 edit_update(fileage, CENTER);
Chris Allegretta271e9722000-11-10 18:15:43 +00001359 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001360 set_modified();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001361
1362 return TRUE;
1363}
1364#endif
1365
1366int do_spell(void)
1367{
1368
Chris Allegrettaff269f82000-12-01 18:46:01 +00001369#if defined(NANO_SMALL)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001370 nano_small_msg();
1371 return (TRUE);
Chris Allegretta7b36c522000-12-06 01:08:10 +00001372#elif defined(DISABLE_SPELLER)
Chris Allegrettaff269f82000-12-01 18:46:01 +00001373 nano_disabled_msg();
1374 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001375#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001376 char *temp;
1377 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001378
Chris Allegretta271e9722000-11-10 18:15:43 +00001379 if ((temp = tempnam(0, "nano.")) == NULL) {
1380 statusbar(_("Could not create a temporary filename: %s"),
1381 strerror(errno));
1382 return 0;
1383 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001384
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001385 if (write_file(temp, 1) == -1) {
1386 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001387 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001388 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001389
Chris Allegretta271e9722000-11-10 18:15:43 +00001390 if (alt_speller)
1391 spell_res = do_alt_speller(temp);
1392 else
1393 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001394
Chris Allegretta271e9722000-11-10 18:15:43 +00001395 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001396
1397 if (spell_res)
1398 statusbar(_("Finished checking spelling"));
1399 else
1400 statusbar(_("Spell checking failed"));
1401
1402 return spell_res;
1403
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001404#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001405}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001406
1407int do_exit(void)
1408{
1409 int i;
1410
1411 if (!ISSET(MODIFIED))
1412 finish(0);
1413
Chris Allegretta30885552000-07-14 01:20:12 +00001414 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001415 i = 1;
1416 } else {
1417 i =
1418 do_yesno(0, 0,
1419 _
1420 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1421 }
1422
1423#ifdef DEBUG
1424 dump_buffer(fileage);
1425#endif
1426
1427 if (i == 1) {
1428 if (do_writeout(1) > 0)
1429 finish(0);
1430 } else if (i == 0)
1431 finish(0);
1432 else
1433 statusbar(_("Cancelled"));
1434
1435 display_main_list();
1436 return 1;
1437}
1438
1439#ifndef NANO_SMALL
1440#ifdef NCURSES_MOUSE_VERSION
1441void do_mouse(void)
1442{
1443 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001444 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001445
1446 if (getmouse(&mevent) == ERR)
1447 return;
1448
1449 /* If mouse not in edit window, return (add help selection later). */
1450 if (!wenclose(edit, mevent.y, mevent.x))
1451 return;
1452
1453 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1454 mevent.y -= 2;
1455
1456 /* Selecting where the cursor is sets the mark.
1457 * Selecting beyond the line length with the cursor at the end of the
1458 * line sets the mark as well.
1459 */
1460 if ((mevent.y == current_y) &&
1461 ((mevent.x == current_x) || (current_x == strlen(current->data)
1462 && (mevent.x >
1463 strlen(current->data))))) {
1464 if (ISSET(VIEW_MODE)) {
1465 print_view_warning();
1466 return;
1467 }
1468 do_mark();
1469 } else if (mevent.y > current_y) {
1470 while (mevent.y > current_y) {
1471 if (current->next != NULL)
1472 current = current->next;
1473 else
1474 break;
1475 current_y++;
1476 }
1477 } else if (mevent.y < current_y) {
1478 while (mevent.y < current_y) {
1479 if (current->prev != NULL)
1480 current = current->prev;
1481 else
1482 break;
1483 current_y--;
1484 }
1485 }
1486 current_x = mevent.x;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001487 placewewant = current_x;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001488 while (foo < current_x) {
1489 if (current->data[foo] == NANO_CONTROL_I) {
Chris Allegrettae10debd2000-08-22 01:26:42 +00001490 current_x -= tabsize - (foo % tabsize);
1491 tab_found = 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001492 } else if (current->data[foo] & 0x80);
1493 else if (current->data[foo] < 32)
Chris Allegrettae10debd2000-08-22 01:26:42 +00001494 current_x--;
1495 foo++;
1496 }
1497 /* This is where tab_found comes in. I can't figure out why,
1498 * but without it any line with a tab will place the cursor
1499 * one character behind. Whatever, this fixes it. */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001500 if (tab_found == 1)
Chris Allegrettae10debd2000-08-22 01:26:42 +00001501 current_x++;
1502
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001503 if (current_x > strlen(current->data))
1504 current_x = strlen(current->data);
1505
1506 update_cursor();
1507 edit_refresh();
1508
1509}
1510#endif
1511#endif
1512
1513/* Handler for SIGHUP */
1514RETSIGTYPE handle_hup(int signal)
1515{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001516 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001517}
1518
Chris Allegretta18f8be02000-09-04 03:20:38 +00001519/* What do we do when we catch the suspend signal */
1520RETSIGTYPE do_suspend(int signal)
1521{
1522
1523 act.sa_handler = SIG_DFL;
1524 sigemptyset(&act.sa_mask);
1525 sigaction(SIGTSTP, &act, NULL);
1526
1527 endwin();
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001528 fprintf(stderr, "\n\n\n\n\nUse \"fg\" to return to nano\n");
Chris Allegretta18f8be02000-09-04 03:20:38 +00001529 raise(SIGTSTP);
1530}
1531
1532/* Restore the suspend handler when we come back into the prog */
1533RETSIGTYPE do_cont(int signal)
1534{
1535
1536 act.sa_handler = do_suspend;
1537 sigemptyset(&act.sa_mask);
1538 sigaction(SIGTSTP, &act, NULL);
1539 initscr();
1540 total_refresh();
1541}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001542
1543void handle_sigwinch(int s)
1544{
1545#ifndef NANO_SMALL
1546 char *tty = NULL;
1547 int fd = 0;
1548 int result = 0;
1549 int i = 0;
1550 struct winsize win;
1551
1552 tty = ttyname(0);
1553 if (!tty)
1554 return;
1555 fd = open(tty, O_RDWR);
1556 if (fd == -1)
1557 return;
1558 result = ioctl(fd, TIOCGWINSZ, &win);
1559 if (result == -1)
1560 return;
1561
1562
1563 COLS = win.ws_col;
1564 LINES = win.ws_row;
1565
1566 center_x = COLS / 2;
1567 center_y = LINES / 2;
1568 editwinrows = LINES - 5 + no_help();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001569 fill = COLS - 8;
1570
1571 free(hblank);
1572 hblank = nmalloc(COLS + 1);
1573
1574 for (i = 0; i <= COLS - 1; i++)
1575 hblank[i] = ' ';
1576 hblank[i] = 0;
1577
1578#ifdef HAVE_NCURSES_H
1579 resizeterm(LINES, COLS);
1580#ifdef HAVE_WRESIZE
1581 if (wresize(topwin, 2, COLS) == ERR)
1582 die(_("Cannot resize top win"));
1583 if (mvwin(topwin, 0, 0) == ERR)
1584 die(_("Cannot move top win"));
1585 if (wresize(edit, editwinrows, COLS) == ERR)
1586 die(_("Cannot resize edit win"));
1587 if (mvwin(edit, 2, 0) == ERR)
1588 die(_("Cannot move edit win"));
1589 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1590 die(_("Cannot resize bottom win"));
1591 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1592 die(_("Cannot move bottom win"));
1593#endif /* HAVE_WRESIZE */
1594#endif /* HAVE_NCURSES_H */
1595
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001596 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001597
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001598 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001599 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001600 }
1601 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001602
1603 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001604 refresh();
Chris Allegretta97accc62000-06-19 05:45:52 +00001605 titlebar();
1606 edit_refresh();
1607 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001608 total_refresh();
1609#endif
1610}
1611
Chris Allegretta756f2202000-09-01 13:32:47 +00001612void signal_init(void)
1613{
Chris Allegretta756f2202000-09-01 13:32:47 +00001614
1615 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
1616 memset(&act, 0, sizeof(struct sigaction));
1617 act.sa_handler = SIG_IGN;
1618 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00001619
Chris Allegretta18f8be02000-09-04 03:20:38 +00001620 if (!ISSET(SUSPEND)) {
Chris Allegretta756f2202000-09-01 13:32:47 +00001621 sigaction(SIGTSTP, &act, NULL);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001622 } else {
Chris Allegretta18f8be02000-09-04 03:20:38 +00001623 act.sa_handler = do_suspend;
1624 sigaction(SIGTSTP, &act, NULL);
1625
1626 act.sa_handler = do_cont;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001627 sigaction(SIGCONT, &act, NULL);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001628 }
1629
Chris Allegretta756f2202000-09-01 13:32:47 +00001630
1631 /* Trap SIGHUP cuz we want to write the file out. */
1632 act.sa_handler = handle_hup;
1633 sigaction(SIGHUP, &act, NULL);
1634
1635 act.sa_handler = handle_sigwinch;
1636 sigaction(SIGWINCH, &act, NULL);
1637
1638}
1639
Chris Allegretta2a42af12000-09-12 23:02:49 +00001640void window_init(void)
1641{
Chris Allegretta92c9dd22000-09-13 14:03:27 +00001642 editwinrows = LINES - 5 + no_help();
1643
Chris Allegretta2a42af12000-09-12 23:02:49 +00001644 /* Setup up the main text window */
1645 edit = newwin(editwinrows, COLS, 2, 0);
1646
1647 /* And the other windows */
1648 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001649 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta2a42af12000-09-12 23:02:49 +00001650}
1651
Chris Allegretta756f2202000-09-01 13:32:47 +00001652void mouse_init(void)
1653{
1654#ifndef NANO_SMALL
1655#ifdef NCURSES_MOUSE_VERSION
1656 if (ISSET(USE_MOUSE)) {
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +00001657 keypad_on(TRUE);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00001658
Chris Allegretta756f2202000-09-01 13:32:47 +00001659 mousemask(BUTTON1_RELEASED, NULL);
1660 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00001661
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001662 } else {
Chris Allegretta756f2202000-09-01 13:32:47 +00001663 mousemask(0, NULL);
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +00001664 keypad_on(FALSE);
Chris Allegretta756f2202000-09-01 13:32:47 +00001665 }
1666#endif
1667#endif
1668
1669}
1670
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001671int do_tab(void)
1672{
1673 do_char('\t');
1674 return 1;
1675}
1676
Chris Allegrettaff269f82000-12-01 18:46:01 +00001677#if !defined(NANO_SMALL) && !defined(DISABLE_JUSTIFY)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001678int empty_line(const char *data)
1679{
1680 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001681 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001682 return 0;
1683
1684 data++;
1685 }
1686
1687 return 1;
1688}
1689
1690int no_spaces(const char *data)
1691{
1692 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001693 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001694 return 0;
1695
1696 data++;
1697 }
1698
1699 return 1;
1700}
1701
1702void justify_format(char *data)
1703{
1704 int i = 0;
1705 int len = strlen(data);
1706
1707 /* Skip first character regardless and leading whitespace. */
1708 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001709 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001710 break;
1711 }
1712
1713 i++; /* (i) is now at least 2. */
1714
1715 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
1716 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001717 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001718 && (data[i - 2] != '.')) {
1719 memmove(data + i, data + i + 1, len - i);
1720 len--;
1721 i--;
1722 }
1723 }
1724}
1725#endif
1726
1727int do_justify(void)
1728{
Chris Allegrettaff269f82000-12-01 18:46:01 +00001729#ifdef NANO_SMALL
1730 nano_small_msg();
1731 return 1;
1732#elif defined(DISABLE_JUSTIFY)
1733 nano_disabled_msg();
1734 return 1;
1735#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001736 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta9149e612000-11-27 00:23:41 +00001737 int initial_y, kbinput;
1738 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001739
1740 if (empty_line(current->data)) {
1741 /* Justify starting at first non-empty line. */
1742 do {
1743 if (!current->next)
1744 return 1;
1745
1746 current = current->next;
1747 current_y++;
1748 }
1749 while (empty_line(current->data));
1750 } else {
1751 /* Search back for the beginning of the paragraph, where
1752 * Paragraph is 1) A line with leading whitespace
1753 * or 2) A line following an empty line.
1754 */
1755 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001756 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001757 break;
1758
1759 current = current->prev;
1760 current_y--;
1761 }
1762
1763 /* First line with leading whitespace may be empty. */
1764 if (empty_line(current->data)) {
1765 if (current->next) {
1766 current = current->next;
1767 current_y++;
1768 } else
1769 return 1;
1770 }
1771 }
1772 initial = current;
1773 initial_y = current_y;
1774
1775 set_modified();
Chris Allegretta9149e612000-11-27 00:23:41 +00001776 cutbak = cutbuffer; /* Got to like cutbak ;) */
1777 cutbuffer = NULL;
1778
1779 tmptop = current;
1780 tmpjust = copy_node(current);
1781 add_to_cutbuffer(tmpjust);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001782 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001783 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001784 && current->next->data[0]) {
1785 filestruct *tmpnode = current->next;
1786 int len = strlen(current->data);
1787 int len2 = strlen(current->next->data);
1788
Chris Allegretta9149e612000-11-27 00:23:41 +00001789 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00001790 tmpjust = copy_node(current->next);
1791 add_to_cutbuffer(tmpjust);
1792
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001793 /* length of both strings plus space between strings and ending \0. */
1794 current->data = nrealloc(current->data, len + len2 + 2);
1795 current->data[len++] = ' ';
1796 current->data[len] = '\0';
1797
1798 strncat(current->data, current->next->data, len2);
1799
1800 unlink_node(tmpnode);
1801 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001802 }
1803
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001804 totsize -= strlen(current->data);
1805
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001806 justify_format(current->data);
1807
1808 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001809 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001810
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001811 if ((strlenpt(current->data) > (fill))
1812 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001813 do {
1814 int i = 0;
1815 int len2 = 0;
1816 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001817
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001818 /* Start at fill , unless line isn't that long (but it
1819 * appears at least fill long with tabs.
1820 */
1821 if (slen > fill)
1822 i = fill;
1823 else
1824 i = slen;
1825 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001826 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001827 ((strlenpt(current->data) - strlen(current->data + i))
1828 <= fill))
1829 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001830 }
1831 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001832 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001833
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001834 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001835
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001836 len2 = strlen(current->data + i + 1);
1837 tmpline->data = nmalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001838
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001839 /* Skip the white space in current. */
1840 memcpy(tmpline->data, current->data + i + 1, len2);
1841 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001842
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001843 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001844
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001845 tmpline->prev = current;
1846 tmpline->next = current->next;
1847 if (current->next != NULL)
1848 current->next->prev = tmpline;
1849
1850 current->next = tmpline;
1851 current = tmpline;
1852 slen -= i + 1;
1853 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001854 } while ((strlenpt(current->data) > (fill))
1855 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001856 }
Chris Allegretta9149e612000-11-27 00:23:41 +00001857 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001858
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001859 if (current->next)
1860 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00001861 else
1862 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001863 current_x = 0;
1864 placewewant = 0;
1865
Adam Rogoyski09f97962000-06-20 02:50:33 +00001866 renumber(initial);
1867 totlines = filebot->lineno;
1868
1869 werase(edit);
1870
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001871 if ((current_y < 0) || (current_y >= editwinrows - 1)
1872 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001873 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001874 center_cursor();
1875 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001876 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001877 }
1878
Adam Rogoyski09f97962000-06-20 02:50:33 +00001879 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00001880 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00001881 /* Change the shortcut list to display the unjustify code */
1882 shortcut_init(1);
1883 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00001884 reset_cursor();
1885
Chris Allegretta07798352000-11-27 22:58:23 +00001886 /* Now get a keystroke and see if it's unjustify, if not unget the keytroke
Chris Allegretta9149e612000-11-27 00:23:41 +00001887 and return */
Chris Allegretta4a9c8582000-11-27 22:59:40 +00001888 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY)
Chris Allegretta07798352000-11-27 22:58:23 +00001889 ungetch(kbinput);
Chris Allegretta9149e612000-11-27 00:23:41 +00001890 else {
1891 /* Else restore the justify we just did (ungrateful user!) */
1892 if (tmptop->prev != NULL)
1893 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00001894 else
1895 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00001896 tmpbot->next->prev = tmptop->prev;
1897 current = tmpbot->next;
1898 tmpbot->next = NULL;
1899 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00001900 if (tmptop->prev == NULL)
1901 edit_refresh();
1902
Chris Allegretta9149e612000-11-27 00:23:41 +00001903 free_filestruct(tmptop);
1904 blank_statusbar_refresh();
1905 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00001906 shortcut_init(0);
1907 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00001908 free_filestruct(cutbuffer);
1909 cutbuffer = cutbak;
1910
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001911 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001912#endif
1913}
1914
Chris Allegretta3bc8c722000-12-10 17:03:25 +00001915#if !defined(NANO_SMALL) && !defined(DISABLE_HELP)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001916void help_init(void)
1917{
1918 int i, sofar = 0;
1919 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegretta220ba692000-12-18 03:40:00 +00001920 char buf[BUFSIZ] = "";
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001921
1922 /* Compute the space needed for the shortcut lists - we add 15 to
1923 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegretta220ba692000-12-18 03:40:00 +00001924 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001925 if (main_list[i].help != NULL)
1926 allocsize += strlen(main_list[i].help) + 15;
1927
Chris Allegretta756f2202000-09-01 13:32:47 +00001928 /* And for the toggle list, we also allocate space for extra text. */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00001929 for (i = 0; i <= TOGGLE_LEN - 1; i++)
Chris Allegretta756f2202000-09-01 13:32:47 +00001930 if (toggles[i].desc != NULL)
1931 allocsize += strlen(toggles[i].desc) + 30;
1932
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001933 allocsize += strlen(help_text_init);
1934
1935 if (help_text != NULL)
1936 free(help_text);
1937
1938 /* Allocate space for the help text */
1939 help_text = nmalloc(allocsize);
1940
1941 /* Now add the text we want */
1942 strcpy(help_text, help_text_init);
1943
1944 /* Now add our shortcut info */
Chris Allegretta220ba692000-12-18 03:40:00 +00001945 for (i = 0; i <= MAIN_LIST_LEN - 1; i++) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001946 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001947
1948 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00001949 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001950 main_list[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001951 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001952 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001953
1954 if (main_list[i].altval > 0)
Chris Allegrettae49f1232000-09-02 07:20:39 +00001955 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001956 main_list[i].altval - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001957 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001958 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001959
Chris Allegretta756f2202000-09-01 13:32:47 +00001960
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001961 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00001962 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001963
Chris Allegretta756f2202000-09-01 13:32:47 +00001964
1965 strcat(help_text, buf);
1966 strcat(help_text, "\n");
1967 }
1968
1969 /* And the toggles... */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00001970 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001971 sofar = snprintf(buf, BUFSIZ,
1972 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00001973
1974 if (toggles[i].desc != NULL)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001975 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
1976 toggles[i].desc);
Chris Allegretta756f2202000-09-01 13:32:47 +00001977
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001978 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00001979 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001980 }
1981
1982}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00001983#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001984
Chris Allegretta756f2202000-09-01 13:32:47 +00001985void do_toggle(int which)
1986{
1987#ifndef NANO_SMALL
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00001988 char *enabled = _("enabled");
1989 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00001990
Chris Allegretta2a42af12000-09-12 23:02:49 +00001991 if (ISSET(toggles[which].flag))
Chris Allegretta756f2202000-09-01 13:32:47 +00001992 UNSET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00001993 else
Chris Allegretta756f2202000-09-01 13:32:47 +00001994 SET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00001995
Chris Allegretta756f2202000-09-01 13:32:47 +00001996 switch (toggles[which].val) {
1997 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00001998 shortcut_init(0);
Chris Allegretta756f2202000-09-01 13:32:47 +00001999 display_main_list();
2000 break;
2001 case TOGGLE_SUSPEND_KEY:
2002 signal_init();
2003 break;
2004 case TOGGLE_MOUSE_KEY:
2005 mouse_init();
2006 break;
2007 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002008 wclear(bottomwin);
2009 wrefresh(bottomwin);
2010 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002011 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002012 edit_refresh();
2013 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002014 break;
2015 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002016
2017 if (!ISSET(toggles[which].flag)) {
2018 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002019 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002020 statusbar("%s %s", toggles[which].desc, enabled);
2021 else
2022 statusbar("%s %s", toggles[which].desc, disabled);
2023 } else {
2024 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002025 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002026 statusbar("%s %s", toggles[which].desc, disabled);
2027 else
2028 statusbar("%s %s", toggles[which].desc, enabled);
2029 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002030 SET(DISABLE_CURPOS);
2031
Chris Allegretta4c780be2000-09-01 17:59:18 +00002032#else
2033 nano_small_msg();
Chris Allegretta756f2202000-09-01 13:32:47 +00002034#endif
2035}
2036
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002037int main(int argc, char *argv[])
2038{
2039 int optchr;
2040 int kbinput; /* Input from keyboard */
2041 long startline = 0; /* Line to try and start at */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002042 int keyhandled = 0; /* Have we handled the keystroke yet? */
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002043 int i, modify_control_seq = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002044 char *argv0;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002045#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002046 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002047#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002048
2049#ifdef HAVE_GETOPT_LONG
2050 int option_index = 0;
2051 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002052#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002053 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002054#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002055 {"version", 0, 0, 'V'},
2056 {"const", 0, 0, 'c'},
2057 {"suspend", 0, 0, 'z'},
2058 {"nowrap", 0, 0, 'w'},
2059 {"nohelp", 0, 0, 'x'},
2060 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002061 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002062#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002063 {"cut", 0, 0, 'k'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002064#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002065 {"autoindent", 0, 0, 'i'},
2066 {"tempfile", 0, 0, 't'},
2067 {"speller", 1, 0, 's'},
2068 {"fill", 1, 0, 'r'},
2069 {"mouse", 0, 0, 'm'},
2070 {"pico", 0, 0, 'p'},
2071 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002072 {"tabsize", 1, 0, 'T'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002073 {0, 0, 0, 0}
2074 };
2075#endif
2076
2077 /* Flag inits... */
2078 SET(FOLLOW_SYMLINKS);
2079
2080#ifndef NANO_SMALL
2081 setlocale(LC_ALL, "");
2082 bindtextdomain(PACKAGE, LOCALEDIR);
2083 textdomain(PACKAGE);
2084#endif
2085
2086#ifdef HAVE_GETOPT_LONG
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002087 while ((optchr = getopt_long(argc, argv, "?T:RVbcefhiklmpr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002088 long_options, &option_index)) != EOF) {
2089#else
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002090 while ((optchr = getopt(argc, argv, "h?T:RVbcefiklmpr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002091#endif
2092
2093 switch (optchr) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002094 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002095 tabsize = atoi(optarg);
2096 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002097 usage(); /* To stop bogus data for tab width */
2098 finish(1);
2099 }
2100 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002101#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002102 case 'R':
2103 SET(USE_REGEXP);
2104 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002105#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002106 case 'V':
2107 version();
2108 exit(0);
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002109 case 'b':
2110 case 'e':
2111 case 'f':
2112 /* Pico compatibility flags */
2113 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002114 case 'c':
2115 SET(CONSTUPDATE);
2116 break;
2117 case 'h':
2118 case '?':
2119 usage();
2120 exit(0);
2121 case 'i':
2122 SET(AUTOINDENT);
2123 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002124#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002125 case 'k':
2126 SET(CUT_TO_END);
2127 break;
Chris Allegretta18bd0292000-07-28 01:18:10 +00002128#else
2129 case 'k':
2130 usage(); /* Oops! You dont really have that option */
2131 finish(1);
Chris Allegrettad19e9912000-07-12 18:14:51 +00002132#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002133 case 'l':
2134 UNSET(FOLLOW_SYMLINKS);
2135 break;
2136 case 'm':
2137 SET(USE_MOUSE);
2138 break;
2139 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002140 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002141 break;
2142 case 'r':
2143 fill = atoi(optarg);
2144 if (fill <= 0) {
2145 usage(); /* To stop bogus data (like a string) */
2146 finish(1);
2147 }
2148 break;
2149 case 's':
2150 alt_speller = nmalloc(strlen(optarg) + 1);
2151 strcpy(alt_speller, optarg);
2152 break;
2153 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002154 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002155 break;
2156 case 'v':
2157 SET(VIEW_MODE);
2158 break;
2159 case 'w':
2160 SET(NO_WRAP);
2161 break;
2162 case 'x':
2163 SET(NO_HELP);
2164 break;
2165 case 'z':
2166 SET(SUSPEND);
2167 break;
2168 default:
2169 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002170 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002171 }
2172
2173 }
2174
2175 argv0 = strrchr(argv[0], '/');
2176 if ((argv0 && strstr(argv0, "pico"))
2177 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002178 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002179
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002180 /* See if there's a non-option in argv (first non-option is the
2181 filename, if +LINE is not given) */
2182 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002183 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002184 else {
2185 /* Look for the +line flag... */
2186 if (argv[optind][0] == '+') {
2187 startline = atoi(&argv[optind][1]);
2188 optind++;
2189 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002190 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002191 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002192 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002193
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002194 } else
2195 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002196 }
2197
2198
2199 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002200 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002201
Chris Allegretta9239d742000-09-06 15:19:18 +00002202#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002203 term = oldterm;
2204 term.c_cc[VINTR] = _POSIX_VDISABLE;
2205 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2206 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002207 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002208#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002209
2210 /* now ncurses init stuff... */
2211 initscr();
2212 savetty();
2213 nonl();
2214 cbreak();
2215 noecho();
2216 timeout(0);
2217
2218 /* Set up some global variables */
2219 global_init();
Chris Allegretta07798352000-11-27 22:58:23 +00002220 shortcut_init(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002221 init_help_msg();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002222#if !defined(NANO_SMALL) && !defined(DISABLE_HELP)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002223 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002224#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002225 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002226
2227#ifdef DEBUG
2228 fprintf(stderr, _("Main: set up windows\n"));
2229#endif
2230
Chris Allegretta2a42af12000-09-12 23:02:49 +00002231 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002232 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002233
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002234#ifdef PDCURSES
2235 /* Must have this for the arrow, et al, keys to even work in
2236 PDCurses+cygwin under Windows */
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +00002237 keypad_on(TRUE);
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002238#endif
2239
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002240#ifdef DEBUG
2241 fprintf(stderr, _("Main: bottom win\n"));
2242#endif
2243 /* Set up up bottom of window */
2244 display_main_list();
2245
2246#ifdef DEBUG
2247 fprintf(stderr, _("Main: open file\n"));
2248#endif
2249
2250 titlebar();
Chris Allegretta31c76662000-11-21 06:20:20 +00002251
2252 /* Now we check to see if argv[optind] is non-null to determine if
2253 we're dealing with a new file or not, not argc == 1... */
2254 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002255 new_file();
2256 else
2257 open_file(filename, 0, 0);
2258
2259 if (startline > 0)
2260 do_gotoline(startline);
2261 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002262 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002263
Robert Siemborski6967eec2000-07-08 14:23:32 +00002264 edit_refresh();
2265 reset_cursor();
2266
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002267 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00002268
2269#ifndef _POSIX_VDISABLE
2270 /* We're going to have to do it the old way, i.e. on cygwin */
2271 raw();
2272#endif
2273
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002274 kbinput = wgetch(edit);
2275 if (kbinput == 27) { /* Grab Alt-key stuff first */
2276 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002277 /* Alt-O, suddenly very important ;) */
Chris Allegretta16e41682000-09-11 22:33:54 +00002278 case 79:
2279 kbinput = wgetch(edit);
2280 if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002281 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002282#ifdef DEBUG
2283 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002284 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2285 kbinput, kbinput);
2286 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002287 }
2288#endif
2289 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002290 case 27:
2291 /* If we get Alt-Alt, the next keystroke should be the same as a
2292 control sequence */
2293 modify_control_seq = 1;
2294 keyhandled = 1;
2295 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002296 case 91:
2297
2298 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002299 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00002300 kbinput = wgetch(edit);
2301 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002302 kbinput = KEY_F(kbinput - 48);
2303 wgetch(edit);
2304 } else if (kbinput >= '7' && kbinput <= '9') {
2305 kbinput = KEY_F(kbinput - 49);
2306 wgetch(edit);
2307 } else if (kbinput == 126)
2308 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00002309
2310#ifdef DEBUG
2311 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002312 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
2313 kbinput, kbinput);
2314 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002315 }
2316#endif
2317
2318 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002319 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00002320 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00002321 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002322 case '0':
2323 kbinput = KEY_F(9);
2324 wgetch(edit);
2325 break;
2326 case '1':
2327 kbinput = KEY_F(10);
2328 wgetch(edit);
2329 break;
2330 case '3':
2331 kbinput = KEY_F(11);
2332 wgetch(edit);
2333 break;
2334 case '4':
2335 kbinput = KEY_F(12);
2336 wgetch(edit);
2337 break;
2338 case 126: /* Hack, make insert key do something
2339 usefile, like insert file */
2340 do_insertfile();
2341 keyhandled = 1;
2342 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002343#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002344 default:
2345 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
2346 kbinput, kbinput);
2347 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002348#endif
2349
2350 }
2351 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002352 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002353 kbinput = NANO_DELETE_KEY;
2354 wgetch(edit);
2355 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002356 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002357 kbinput = NANO_END_KEY;
2358 wgetch(edit);
2359 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002360 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00002361 kbinput = KEY_PPAGE;
2362 wgetch(edit);
2363 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002364 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00002365 kbinput = KEY_NPAGE;
2366 wgetch(edit);
2367 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002368 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00002369 kbinput = wgetch(edit);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002370 if (kbinput >= 'A' && kbinput <= 'E')
2371 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00002372 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002373 case 'A':
2374 kbinput = KEY_UP;
2375 break;
2376 case 'B':
2377 kbinput = KEY_DOWN;
2378 break;
2379 case 'C':
2380 kbinput = KEY_RIGHT;
2381 break;
2382 case 'D':
2383 kbinput = KEY_LEFT;
2384 break;
2385 case 'H':
2386 kbinput = KEY_HOME;
2387 break;
2388 case 'F':
2389 kbinput = KEY_END;
2390 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002391 default:
2392#ifdef DEBUG
2393 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
2394 kbinput, kbinput);
2395#endif
2396 break;
2397 }
2398 break;
2399 default:
2400
2401 /* Check for the altkey defs.... */
2402 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
2403 if (kbinput == main_list[i].altval ||
2404 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002405 kbinput = main_list[i].val;
2406 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002407 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002408#ifndef NANO_SMALL
2409 /* And for toggle switches */
2410 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
2411 if (kbinput == toggles[i].val ||
2412 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002413 do_toggle(i);
2414 keyhandled = 1;
2415 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002416 }
2417#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002418#ifdef DEBUG
2419 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
2420 kbinput);
2421#endif
2422 break;
2423 }
2424 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002425 /* If the modify_control_seq is set, we received an Alt-Alt
2426 sequence before this, so we make this key a control sequence
2427 by subtracting 64 or 96, depending on its value. */
2428 if (!keyhandled && modify_control_seq) {
2429 if (kbinput >= 'A' && kbinput < 'a')
2430 kbinput -= 64;
2431 else if (kbinput >= 'a' && kbinput <= 'z')
2432 kbinput -= 96;
2433
2434 modify_control_seq = 0;
2435 }
2436
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002437 /* Look through the main shortcut list to see if we've hit a
2438 shortcut key */
Chris Allegretta756f2202000-09-01 13:32:47 +00002439 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002440 if (kbinput == main_list[i].val ||
2441 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
2442 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
2443 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
2444 print_view_warning();
2445 else
2446 main_list[i].func();
2447 keyhandled = 1;
2448 }
2449 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002450 /* If we're in raw mode or using Alt-Alt-x, we have to catch
2451 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00002452 if (kbinput == 17 || kbinput == 19)
2453 keyhandled = 1;
2454
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002455 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00002456 if (kbinput == 26) {
2457 if (ISSET(SUSPEND))
2458 do_suspend(0);
2459 keyhandled = 1;
2460 }
Chris Allegretta9239d742000-09-06 15:19:18 +00002461
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002462 /* Last gasp, stuff that's not in the main lists */
2463 if (!keyhandled)
2464 switch (kbinput) {
2465#ifndef NANO_SMALL
2466#ifdef NCURSES_MOUSE_VERSION
2467 case KEY_MOUSE:
2468 do_mouse();
2469 break;
2470#endif
2471#endif
2472 case 0: /* Erg */
2473 do_next_word();
2474 break;
2475 case 331: /* Stuff that we don't want to do squat */
2476 case -1:
2477 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002478#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002479 case 541: /* ???? */
2480 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00002481 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002482 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00002483 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002484#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002485
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002486 break;
2487 default:
2488#ifdef DEBUG
2489 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
2490#endif
2491 /* We no longer stop unhandled sequences so that people with
2492 odd character sets can type... */
2493
2494 if (ISSET(VIEW_MODE)) {
2495 print_view_warning();
2496 break;
2497 }
2498 do_char(kbinput);
2499 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002500 if (ISSET(CONSTUPDATE)) {
2501 if (ISSET(DISABLE_CURPOS))
2502 UNSET(DISABLE_CURPOS);
2503 else
2504 do_cursorpos();
2505 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002506
2507 reset_cursor();
2508 wrefresh(edit);
2509 keyhandled = 0;
2510 }
2511
2512 getchar();
2513 finish(0);
2514
2515}