blob: 890293bc3b1ea27c3fbfa95284f1729bab8c88da [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 Allegrettaa2ea1932000-06-06 05:53:49 +000067static char *help_text_init = "";
68 /* Initial message, not including shortcuts */
Chris Allegretta18f8be02000-09-04 03:20:38 +000069static struct sigaction act; /* For all out fun signal handlers */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000070
Chris Allegretta27eb13f2000-11-05 16:52:21 +000071char *last_search = NULL; /* Last string we searched for */
72char *last_replace = NULL; /* Last replacement string */
73int search_last_line; /* Is this the last search line? */
74
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +000075void keypad_on(int yesno)
76{
77 keypad(edit, yesno);
78 keypad(bottomwin, yesno);
79}
80
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000081/* What we do when we're all set to exit */
82RETSIGTYPE finish(int sigage)
83{
84 if (!ISSET(NO_HELP)) {
85 mvwaddstr(bottomwin, 1, 0, hblank);
86 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000087 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000088 mvwaddstr(bottomwin, 0, 0, hblank);
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +000089
90 /* Apparently you REALLY can't get away with not calling keypad()
91 or your window looks awful when it exits. so we just call it right
92 before we exit, muhaha :-) */
93 keypad_on(TRUE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000094 wrefresh(bottomwin);
95 endwin();
96
97 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +000098 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000099
100 exit(sigage);
101}
102
103/* Die (gracefully?) */
104void die(char *msg, ...)
105{
106 va_list ap;
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000107 char *name;
108 int i;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000109
110 va_start(ap, msg);
111 vfprintf(stderr, msg, ap);
112 va_end(ap);
113
114 /* if we can't save we have REAL bad problems,
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000115 * but we might as well TRY. */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000116 if (filename[0] == '\0') {
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000117 name = "nano.save";
118 i = write_file(name, 1);
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000119 } else {
Chris Allegrettae7a58932000-12-02 02:36:22 +0000120
121 char *buf = nmalloc(strlen(filename) + 6);
122 strcpy(buf, filename);
123 strcat(buf, ".save");
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000124 i = write_file(buf, 1);
125 name = buf;
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000126 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000127 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000128 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000129
130 clear();
131 refresh();
132 resetty();
133 endwin();
134
135 fprintf(stderr, msg);
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000136 if (i != -1)
137 fprintf(stderr, _("\nBuffer written to %s\n"), name);
138 else
Chris Allegretta9756d622000-12-03 03:06:45 +0000139 fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000140
141 exit(1); /* We have a problem: exit w/ errorlevel(1) */
142}
143
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000144void print_view_warning(void)
145{
146 statusbar(_("Key illegal in VIEW mode"));
147}
148
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000149void clear_filename(void)
150{
151 if (filename != NULL)
152 free(filename);
153 filename = nmalloc(1);
154 filename[0] = 0;
155}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000156
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000157/* Initialize global variables - no better way for now */
158void global_init(void)
159{
160 int i;
161
162 center_x = COLS / 2;
163 center_y = LINES / 2;
164 current_x = 0;
165 current_y = 0;
166 editwinrows = LINES - 5 + no_help();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000167 fileage = NULL;
168 cutbuffer = NULL;
169 current = NULL;
170 edittop = NULL;
171 editbot = NULL;
172 totlines = 0;
173 placewewant = 0;
174 if (!fill)
175 fill = COLS - 8;
176 hblank = nmalloc(COLS + 1);
177
178 /* Thanks BG for this bit... */
179 for (i = 0; i <= COLS - 1; i++)
180 hblank[i] = ' ';
181 hblank[i] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000182}
183
184void init_help_msg(void)
185{
186
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000187#if !defined(NANO_SMALL) && !defined(DISABLE_HELP)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000188
189 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000190 _(" nano help text\n\n "
191 "The nano editor is designed to emulate the functionality and "
192 "ease-of-use of the UW Pico text editor. There are four main "
193 "sections of the editor: The top line shows the program "
194 "version, the current filename being edited, and whether "
195 "or not the file has been modified. Next is the main editor "
196 "window showing the file being edited. The status line is "
197 "the third line from the bottom and shows important messages. "
198 "The bottom two lines show the most commonly used shortcuts "
199 "in the editor.\n\n "
200 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000201 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000202 "with the Control (Ctrl) key. Escape-key sequences are notated "
203 "with the Meta (M) symbol and can be entered using either the "
204 "Esc, Alt or Meta key depending on your keyboard setup. The "
205 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000206 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000207#endif
208
209}
210
211/* Make a copy of a node to a pointer (space will be malloc()ed) */
212filestruct *copy_node(filestruct * src)
213{
214 filestruct *dst;
215
216 dst = nmalloc(sizeof(filestruct));
217 dst->data = nmalloc(strlen(src->data) + 1);
218
219 dst->next = src->next;
220 dst->prev = src->prev;
221
222 strcpy(dst->data, src->data);
223 dst->lineno = src->lineno;
224
225 return dst;
226}
227
228/* Unlink a node from the rest of the struct */
229void unlink_node(filestruct * fileptr)
230{
231 if (fileptr->prev != NULL)
232 fileptr->prev->next = fileptr->next;
233
234 if (fileptr->next != NULL)
235 fileptr->next->prev = fileptr->prev;
236}
237
238void delete_node(filestruct * fileptr)
239{
240 if (fileptr->data != NULL)
241 free(fileptr->data);
242 free(fileptr);
243}
244
245/* Okay, now let's duplicate a whole struct! */
246filestruct *copy_filestruct(filestruct * src)
247{
248 filestruct *dst, *tmp, *head, *prev;
249
250 head = copy_node(src);
251 dst = head; /* Else we barf on copying just one line */
252 head->prev = NULL;
253 tmp = src->next;
254 prev = head;
255
256 while (tmp != NULL) {
257 dst = copy_node(tmp);
258 dst->prev = prev;
259 prev->next = dst;
260
261 prev = dst;
262 tmp = tmp->next;
263 }
264
265 dst->next = NULL;
266 return head;
267}
268
269/* Free() a single node */
270int free_node(filestruct * src)
271{
272 if (src == NULL)
273 return 0;
274
275 if (src->next != NULL)
276 free(src->data);
277 free(src);
278 return 1;
279}
280
281int free_filestruct(filestruct * src)
282{
283 filestruct *fileptr = src;
284
285 if (src == NULL)
286 return 0;
287
288 while (fileptr->next != NULL) {
289 fileptr = fileptr->next;
290 free_node(fileptr->prev);
291
292#ifdef DEBUG
293 fprintf(stderr, _("free_node(): free'd a node, YAY!\n"));
294#endif
295 }
296 free_node(fileptr);
297#ifdef DEBUG
298 fprintf(stderr, _("free_node(): free'd last node.\n"));
299#endif
300
301 return 1;
302}
303
304int renumber_all(void)
305{
306 filestruct *temp;
307 long i = 1;
308
309 for (temp = fileage; temp != NULL; temp = temp->next) {
310 temp->lineno = i++;
311 }
312
313 return 0;
314}
315
316int renumber(filestruct * fileptr)
317{
318 filestruct *temp;
319
320 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
321 renumber_all();
322 return 0;
323 }
324 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000325 if (temp->prev != NULL)
326 temp->lineno = temp->prev->lineno + 1;
327 else
328 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000329 }
330
331 return 0;
332}
333
334/* Fix the memory allocation for a string */
335void align(char **strp)
336{
337 /* There was a serious bug here: the new address was never
338 stored anywhere... */
339
340 *strp = nrealloc(*strp, strlen(*strp) + 1);
341}
342
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000343/* Null a string at a certain index and align it */
344void null_at(char *data, int index)
345{
346 data[index] = 0;
347 align(&data);
348}
349
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000350void usage(void)
351{
352#ifdef HAVE_GETOPT_LONG
353 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
354 printf(_("Option Long option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000355 printf(_
356 (" -T --tabsize=[num] Set width of a tab to num\n"));
Chris Allegretta805c26d2000-09-06 13:39:17 +0000357#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000358 printf(_
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000359 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000360#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000361 printf
362 (_
363 (" -V --version Print version information and exit\n"));
364 printf(_
365 (" -c --const Constantly show cursor position\n"));
366 printf(_
367 (" -h --help Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000368#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000369 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000370 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000371#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000372 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000373 (" -i --autoindent Automatically indent new lines\n"));
374 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000375 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000376#ifndef NANO_SMALL
377#ifdef NCURSES_MOUSE_VERSION
378 printf(_(" -m --mouse Enable mouse\n"));
379#endif
380#endif
381 printf
382 (_
383 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
384 printf(_
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000385 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000386 printf(_
387 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
388 printf(_
389 (" -t --tempfile Auto save on exit, don't prompt\n"));
390 printf(_
391 (" -v --view View (read only) mode\n"));
392 printf(_
393 (" -w --nowrap Don't wrap long lines\n"));
394 printf(_
395 (" -x --nohelp Don't show help window\n"));
396 printf(_
397 (" -z --suspend Enable suspend\n"));
398 printf(_
399 (" +LINE Start at line number LINE\n"));
400#else
401 printf(_("Usage: nano [option] +LINE <file>\n\n"));
402 printf(_("Option Meaning\n"));
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000403 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000404 printf(_(" -R Use regular expressions for search\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000405 printf(_(" -V Print version information and exit\n"));
406 printf(_(" -c Constantly show cursor position\n"));
407 printf(_(" -h Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000408#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +0000409 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000410#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000411 printf(_(" -i Automatically indent new lines\n"));
412 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000413 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000414#ifndef NANO_SMALL
415#ifdef NCURSES_MOUSE_VERSION
416 printf(_(" -m Enable mouse\n"));
417#endif
418#endif
419 printf(_
420 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
421 printf(_(" -s [prog] Enable alternate speller\n"));
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000422 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000423 printf(_(" -t Auto save on exit, don't prompt\n"));
424 printf(_(" -v View (read only) mode\n"));
425 printf(_(" -w Don't wrap long lines\n"));
426 printf(_(" -x Don't show help window\n"));
427 printf(_(" -z Enable suspend\n"));
428 printf(_(" +LINE Start at line number LINE\n"));
429#endif
430 exit(0);
431}
432
433void version(void)
434{
435 printf(_(" nano version %s by Chris Allegretta (compiled %s, %s)\n"),
436 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000437 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000438 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000439 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000440
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000441#ifdef NANO_SMALL
442 printf(" --enable-tiny");
443#endif
444#ifdef NANO_EXTRA
445 printf(" --enable-extra");
446#endif
447#ifdef DISABLE_TABCOMP
448 printf(" --disable-tabcomp");
449#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000450#ifdef DISABLE_JUSTIFY
451 printf(" --disable-justify");
452#endif
Chris Allegretta7b36c522000-12-06 01:08:10 +0000453#ifdef DISABLE_SPELLER
454 printf(" --disable-speller");
Chris Allegrettaff269f82000-12-01 18:46:01 +0000455#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000456#ifdef USE_SLANG
457 printf(" --with-slang");
458#endif
459 printf("\n");
460
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000461}
462
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000463filestruct *make_new_node(filestruct * prevnode)
464{
465 filestruct *newnode;
466
467 newnode = nmalloc(sizeof(filestruct));
468 newnode->data = NULL;
469
470 newnode->prev = prevnode;
471 newnode->next = NULL;
472
473 if (prevnode != NULL)
474 newnode->lineno = prevnode->lineno + 1;
475
476 return newnode;
477}
478
Chris Allegretta7975ed82000-07-28 00:58:35 +0000479/* Splice a node into an existing filestruct */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000480void splice_node(filestruct * begin, filestruct * new, filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000481{
482 new->next = end;
483 new->prev = begin;
484 begin->next = new;
485 if (end != NULL)
486 end->prev = new;
487}
488
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000489int do_mark()
490{
491#ifdef NANO_SMALL
492 nano_small_msg();
493#else
494 if (!ISSET(MARK_ISSET)) {
495 statusbar(_("Mark Set"));
496 SET(MARK_ISSET);
497 mark_beginbuf = current;
498 mark_beginx = current_x;
499 } else {
500 statusbar(_("Mark UNset"));
501 UNSET(MARK_ISSET);
502 mark_beginbuf = NULL;
503 mark_beginx = 0;
504
505 edit_refresh();
506 }
507#endif
508 return 1;
509}
510
511int no_help(void)
512{
513 if ISSET
514 (NO_HELP)
515 return 2;
516 else
517 return 0;
518}
519
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000520#ifdef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000521void nano_small_msg(void)
522{
523 statusbar("Sorry, this function not available with nano-tiny option");
524}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000525#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000526
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000527#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000528void nano_disabled_msg(void)
529{
530 statusbar("Sorry, support for this function has been disabled");
531}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000532#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000533
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000534/* The user typed a printable character; add it to the edit buffer */
535void do_char(char ch)
536{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000537 /* magic-line: when a character is inserted on the current magic line,
538 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000539 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000540 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000541 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000542 }
543
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000544 /* More dangerousness fun =) */
545 current->data = nrealloc(current->data, strlen(current->data) + 2);
546 memmove(&current->data[current_x + 1],
547 &current->data[current_x],
548 strlen(current->data) - current_x + 1);
549 current->data[current_x] = ch;
550 do_right();
551
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000552 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000553 check_wrap(current, ch);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000554 set_modified();
555 check_statblank();
556 UNSET(KEEP_CUTBUFFER);
557 totsize++;
558
559}
560
561/* Someone hits return *gasp!* */
562int do_enter(filestruct * inptr)
563{
564 filestruct *new;
565 char *tmp, *spc;
566 int extra = 0;
567
568 new = make_new_node(inptr);
569 tmp = &current->data[current_x];
570 current_x = 0;
571
572 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
573 if (ISSET(AUTOINDENT)) {
574 spc = current->data;
575 if (spc) {
576 while ((*spc == ' ') || (*spc == '\t')) {
577 extra++;
578 spc++;
579 current_x++;
580 }
581 new->data = nmalloc(strlen(tmp) + extra + 1);
582 strncpy(new->data, current->data, extra);
583 strcpy(&new->data[extra], tmp);
584 }
585 } else {
586 new->data = nmalloc(strlen(tmp) + 1);
587 strcpy(new->data, tmp);
588 }
589 *tmp = 0;
590
Chris Allegrettada721be2000-07-31 01:26:42 +0000591 if (inptr->next == NULL) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000592 filebot = new;
593 editbot = new;
594 }
Chris Allegretta7975ed82000-07-28 00:58:35 +0000595 splice_node(inptr, new, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000596
597 totsize++;
598 renumber(current);
599 current = new;
600 align(&current->data);
601
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000602 /* The logic here is as follows:
603 * -> If we are at the bottom of the buffer, we want to recenter
604 * (read: rebuild) the screen and forcably move the cursor.
605 * -> otherwise, we want simply to redraw the screen and update
606 * where we think the cursor is.
607 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000608 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000609 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000610 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000611 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000612 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000613 edit_refresh();
614 update_cursor();
615 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000616
617 totlines++;
618 set_modified();
619
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000620 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000621 return 1;
622}
623
624int do_enter_void(void)
625{
626 return do_enter(current);
627}
628
629void do_next_word(void)
630{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000631 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000632 int i;
633
634 if (current == NULL)
635 return;
636
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000637 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000638 i = current_x;
639 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
640 if (fileptr == current) {
641 while (isalnum((int) fileptr->data[i])
642 && fileptr->data[i] != 0)
643 i++;
644
645 if (fileptr->data[i] == 0) {
646 i = 0;
647 continue;
648 }
649 }
650 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
651 i++;
652
653 if (fileptr->data[i] != 0)
654 break;
655
656 i = 0;
657 }
658 if (fileptr == NULL)
659 current = filebot;
660 else
661 current = fileptr;
662
663 current_x = i;
664 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000665
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000666 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000667 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000668 else {
669 /* If we've jumped lines, refresh the old line. We can't just use
670 * current->prev here, because we may have skipped over some blank
671 * lines, in which case the previous line is the wrong one.
672 */
673 if (current != old)
674 update_line(old, 0);
675
676 update_line(current, current_x);
677 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000678
679}
680
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000681void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000682{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000683 int i = 0; /* Index into ->data for line. */
684 int i_tabs = 0; /* Screen position of ->data[i]. */
685 int last_word_end = -1; /* Location of end of last word found. */
686 int current_word_start = -1; /* Location of start of current word. */
687 int current_word_start_t = -1; /* Location of start of current word screen position. */
688 int current_word_end = -1; /* Location of end of current word */
689 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000690 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000691
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000692 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000693 int right = 0;
694 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000695
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000696 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000697
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000698 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000699 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000700 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000701
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000702 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000703 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000704
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000705 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000706 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000707 i++;
708 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000709 if (inptr->data[i] < 32)
710 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000711 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000712
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000713 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000714 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000715 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000716 } else {
717 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000718 current_word_end_t = i_tabs - 1;
719 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000720 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000721
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000722 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000723 if (i_tabs % tabsize != 0);
724 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000725 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000726
Adam Rogoyski09f97962000-06-20 02:50:33 +0000727 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000728 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000729 }
730
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000731 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000732 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000733 * a) one word takes up the whole line with no starting spaces.
734 * - do nothing and return.
735 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000736 * - word starts new line.
737 * - keep white space on original line up to the cursor.
738 * *) cursor is after word at wrap point
739 * - either it's all white space after word, and this routine isn't called.
740 * - or we are actually in case 2 (2 words).
741 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000742 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000743 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000744 * - white space at end of original line is cleared, unless
745 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000746 * b) cursor is at the word at the wrap point.
747 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000748 * 1. pressed a space and at first character of wrap point word.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000749 * - white space on original line is kept to where cursor was.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000750 * 2. pressed non space (or space elsewhere).
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000751 * - white space at end of original line is cleared.
752 * c) cursor is past the word at the wrap point.
753 * - word at wrap point starts a new line.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000754 * - white space at end of original line is cleared
755 */
756
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000757 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000758
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000759 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000760 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000761 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000762 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000763 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000764 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000765 i++;
766 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000767 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000768 current_word_end = i;
769 break;
770 }
771 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000772
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000773 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000774 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000775 return;
776 }
777 if (current_x >= last_word_end) {
778 right = (current_x - current_word_start) + 1;
779 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000780 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000781 }
782
783 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
784 strcpy(temp->data, &inptr->data[current_word_start]);
785 inptr->data = nrealloc(inptr->data, last_word_end + 2);
786 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000787 } else
788 /* Category 1b: one word on the line and word not taking up whole line
789 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000790 if (last_word_end == -1) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000791 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
792 strcpy(temp->data, &inptr->data[current_word_start]);
793
794 /* Inside word, remove it from original, and move cursor to right spot. */
795 if (current_x >= current_word_start) {
796 right = current_x - current_word_start;
797 current_x = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000798 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000799 }
800
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000801 null_at(inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000802
803 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
804 mark_beginbuf = temp;
805 mark_beginx = 0;
806 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000807 }
808
809 /* Category 2: two or more words on the line. */
810 else {
811
812 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000813 if (current_x < current_word_start) {
814 temp->data =
815 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
816 strcpy(temp->data, &inptr->data[current_word_start]);
817
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000818 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000819 i = current_word_start - 1;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000820 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000821 i--;
822 assert(i >= 0);
823 }
824 } else if (current_x <= last_word_end)
825 i = last_word_end - 1;
826 else
827 i = current_x;
828
829 inptr->data = nrealloc(inptr->data, i + 2);
830 inptr->data[i + 1] = 0;
831 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000832
833
834 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000835 else if ((current_x >= current_word_start)
836 && (current_x <= (current_word_end + 1))) {
837 temp->data =
838 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000839 strcpy(temp->data, &inptr->data[current_word_start]);
840
841 down = 1;
842
843 right = current_x - current_word_start;
844 i = current_word_start - 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000845 if (isspace((int) input_char)
846 && (current_x == current_word_start)) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000847 current_x = current_word_start;
848
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000849 null_at(inptr->data, current_word_start);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000850 } else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000851
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000852 while (isspace((int) inptr->data[i])) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000853 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000854 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000855 }
856 inptr->data = nrealloc(inptr->data, i + 2);
857 inptr->data[i + 1] = 0;
858 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000859 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000860
861
862 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000863 else {
864 temp->data =
865 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000866 strcpy(temp->data, &inptr->data[current_word_start]);
867
868 down = 1;
869 right = current_x - current_word_start;
870
871 current_x = current_word_start;
872 i = current_word_start - 1;
873
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000874 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000875 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000876 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000877 inptr->data = nrealloc(inptr->data, i + 2);
878 inptr->data[i + 1] = 0;
879 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000880 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000881 }
882
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000883 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000884 if (ISSET(SAMELINEWRAP) && inptr->next) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000885 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
886 char *p =
887 nmalloc(strlen(temp->data) + strlen(inptr->next->data) + 2);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000888 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000889
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000890 strcpy(p, temp->data);
891 strcat(p, " ");
892 strcat(p, inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000893
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000894 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000895 inptr->next->data = p;
896
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000897 free(temp->data);
898 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000899
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000900 current_x = old_x;
901 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000902 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000903 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000904 else {
905 temp->prev = inptr;
906 temp->next = inptr->next;
907
908 if (inptr->next)
909 inptr->next->prev = temp;
910 inptr->next = temp;
911
912 if (!temp->next)
913 filebot = temp;
914
915 SET(SAMELINEWRAP);
916 }
917
918
919 totlines++;
Robert Siemborskia417ddc2000-07-24 23:18:48 +0000920 /* Everything about it makes me want this line here but it causes
921 * totsize to be high by one for some reason. Sigh. (Rob) */
922 /* totsize++; */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000923
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000924 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +0000925 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000926
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000927
928 /* Move the cursor to the new line if appropriate. */
929 if (down) {
930 do_right();
931 }
932
933 /* Move the cursor to the correct spot in the line if appropriate. */
934 while (right--) {
935 do_right();
936 }
937
Chris Allegretta234a34d2000-07-29 04:33:38 +0000938 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000939 reset_cursor();
940 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000941}
942
943/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000944void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000945{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000946 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000947#ifdef DEBUG
948 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
949 inptr->data);
950#endif
951
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000952 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000953 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000954 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000955 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000956
957 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000958 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000959
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000960 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +0000961 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000962
Adam Rogoyski09f97962000-06-20 02:50:33 +0000963 if (!inptr->data[i])
964 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000965
Adam Rogoyski09f97962000-06-20 02:50:33 +0000966 /* String must be at least 1 character long. */
967 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000968 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +0000969 if (!char_found)
970 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000971 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000972 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000973 } else
974 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000975 }
Adam Rogoyski09f97962000-06-20 02:50:33 +0000976
977 if (char_found == 2)
978 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000979 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000980}
981
982/* Stuff we do when we abort from programs and want to clean up the
983 * screen. This doesnt do much right now.
984 */
985void do_early_abort(void)
986{
987 blank_statusbar_refresh();
988}
989
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000990int do_backspace(void)
991{
992 filestruct *previous, *tmp;
993
994 if (current_x != 0) {
995 /* Let's get dangerous */
996 memmove(&current->data[current_x - 1], &current->data[current_x],
997 strlen(current->data) - current_x + 1);
998#ifdef DEBUG
999 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1000#endif
1001 align(&current->data);
1002 do_left();
1003 } else {
1004 if (current == fileage)
1005 return 0; /* Can't delete past top of file */
1006
1007 previous = current->prev;
1008 current_x = strlen(previous->data);
1009 previous->data = nrealloc(previous->data,
1010 strlen(previous->data) +
1011 strlen(current->data) + 1);
1012 strcat(previous->data, current->data);
1013
1014 tmp = current;
1015 unlink_node(current);
1016 delete_node(current);
1017 if (current == edittop) {
1018 if (previous->next)
1019 current = previous->next;
1020 else
1021 current = previous;
Chris Allegrettada721be2000-07-31 01:26:42 +00001022 page_up_center();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001023 } else {
1024 if (previous->next)
1025 current = previous->next;
1026 else
1027 current = previous;
1028 update_line(current, current_x);
1029 }
1030
1031 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001032 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001033 filebot = current;
1034 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001035
1036 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001037 line we're on now is NOT blank. if it is blank we
1038 can just use IT for the magic line. This is how Pico
1039 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001040 if (strcmp(current->data, "")) {
1041 new_magicline();
1042 fix_editbot();
1043 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001044 }
1045
1046 current = previous;
1047 renumber(current);
1048 previous_line();
1049 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001050#ifdef DEBUG
1051 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1052#endif
1053
1054 }
1055
1056 totsize--;
1057 set_modified();
1058 UNSET(KEEP_CUTBUFFER);
1059 edit_refresh();
1060 return 1;
1061}
1062
1063int do_delete(void)
1064{
1065 filestruct *foo;
1066
1067 if (current_x != strlen(current->data)) {
1068 /* Let's get dangerous */
1069 memmove(&current->data[current_x], &current->data[current_x + 1],
1070 strlen(current->data) - current_x);
1071
1072 align(&current->data);
1073
1074 } else if (current->next != NULL) {
1075 current->data = nrealloc(current->data,
1076 strlen(current->data) +
1077 strlen(current->next->data) + 1);
1078 strcat(current->data, current->next->data);
1079
1080 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001081 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001082 filebot = current;
1083 editbot = current;
1084 }
1085
1086 unlink_node(foo);
1087 delete_node(foo);
1088 update_line(current, current_x);
1089
Chris Allegretta28a0f892000-07-05 22:47:54 +00001090 /* Please see the comment in do_basckspace if you don't understand
1091 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001092 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001093 new_magicline();
1094 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001095 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001096 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001097 renumber(current);
1098 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001099 } else
1100 return 0;
1101
1102 totsize--;
1103 set_modified();
1104 UNSET(KEEP_CUTBUFFER);
1105 edit_refresh();
1106 return 1;
1107}
1108
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001109void wrap_reset(void)
1110{
1111 UNSET(SAMELINEWRAP);
1112}
1113
Chris Allegretta7b36c522000-12-06 01:08:10 +00001114#if !defined(NANO_SMALL) && !defined(DISABLE_SPELLER)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001115
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001116int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001117{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001118 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001119 filestruct *begin;
1120 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001121
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001122 /* save where we are */
1123 begin = current;
1124 beginx = current_x + 1;
1125
1126 /* save the current search/replace strings */
1127 search_init_globals();
1128 save_search = mallocstrcpy(save_search, last_search);
1129 save_replace = mallocstrcpy(save_replace, last_replace);
1130
1131 /* set search/replace strings to mis-spelt word */
1132 prevanswer = mallocstrcpy(prevanswer, word);
1133 last_search = mallocstrcpy(last_search, word);
1134 last_replace = mallocstrcpy(last_replace, word);
1135
1136 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001137 current = fileage;
1138 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001139
1140 search_last_line = FALSE;
1141
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001142 edit_update(fileage, TOP);
1143
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001144 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001145 if (findnextstr(TRUE, fileage, beginx_top, prevanswer) != NULL)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001146 {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001147 do_replace_highlight(TRUE, prevanswer);
1148
1149 /* allow replace word to be corrected */
1150 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1151 _("Edit a replacement"));
1152
1153 do_replace_highlight(FALSE, prevanswer);
1154
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001155 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001156 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001157 current_x = beginx_top;
1158
1159 search_last_line = FALSE;
1160
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001161 j = i;
1162 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001163 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001164
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001165 /* restore the search/replace strings */
1166 last_search = mallocstrcpy(last_search, save_search);
1167 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001168
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001169 /* restore where we were */
1170 current = begin;
1171 current_x = beginx - 1;
1172
1173 edit_update(current, CENTER);
1174
1175 if (i == -1)
1176 return FALSE;
1177
1178 return TRUE;
1179}
1180#endif
1181
Chris Allegretta7b36c522000-12-06 01:08:10 +00001182#if !defined(NANO_SMALL) && !defined(DISABLE_SPELLER)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001183
1184/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001185int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001186{
Chris Allegretta271e9722000-11-10 18:15:43 +00001187 char *read_buff, *read_buff_ptr, *read_buff_word;
1188 long pipe_buff_size;
1189 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001190 int spell_status;
1191 pid_t pid_spell;
1192 ssize_t bytesread;
1193
Chris Allegretta271e9722000-11-10 18:15:43 +00001194 /* Create a pipe to spell program */
1195
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001196 if (pipe(in_fd) == -1)
1197 return FALSE;
1198
Chris Allegretta271e9722000-11-10 18:15:43 +00001199 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001200
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001201 if ( (pid_spell = fork()) == 0) {
1202
1203 /* Child continues, (i.e. future spell process) */
1204
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001205 close(in_fd[0]);
1206
Chris Allegretta271e9722000-11-10 18:15:43 +00001207 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001208
Chris Allegretta271e9722000-11-10 18:15:43 +00001209 if ( (tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
1210
1211 close(in_fd[1]);
1212 exit(1);
1213 }
1214
1215 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1216
1217 close(tempfile_fd);
1218 close(in_fd[1]);
1219 exit(1);
1220 }
1221 close(tempfile_fd);
1222
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001223
Chris Allegretta271e9722000-11-10 18:15:43 +00001224 /* send spell's standard out to the pipe */
1225
1226 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1227
1228 close(in_fd[1]);
1229 exit(1);
1230 }
1231 close(in_fd[1]);
1232
1233 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001234 execlp("spell", "spell", NULL);
1235
Chris Allegretta271e9722000-11-10 18:15:43 +00001236 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001237
Chris Allegretta271e9722000-11-10 18:15:43 +00001238 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001239 }
1240
1241 /* Parent continues here */
1242
Chris Allegretta271e9722000-11-10 18:15:43 +00001243 close(in_fd[1]);
1244
1245 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001246
1247 if (pid_spell < 0) {
1248
Chris Allegretta271e9722000-11-10 18:15:43 +00001249 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001250 return FALSE;
1251 }
1252
Chris Allegretta271e9722000-11-10 18:15:43 +00001253 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001254
Chris Allegretta271e9722000-11-10 18:15:43 +00001255 if ( (pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001256
Chris Allegretta271e9722000-11-10 18:15:43 +00001257 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001258 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001259 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001260
Chris Allegretta271e9722000-11-10 18:15:43 +00001261 read_buff = nmalloc( pipe_buff_size + 1 );
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001262
Chris Allegretta271e9722000-11-10 18:15:43 +00001263 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001264
Chris Allegretta271e9722000-11-10 18:15:43 +00001265 while ( (bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001266
Chris Allegretta271e9722000-11-10 18:15:43 +00001267 read_buff[bytesread] = (char) NULL;
1268 read_buff_word = read_buff_ptr = read_buff;
1269
1270 while (*read_buff_ptr != (char) NULL) {
1271
1272 /* Windows version may need to process additional char '\r' */
1273
1274 /* Possible problem here if last word not followed by '\n' */
1275
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001276 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001277 *read_buff_ptr = (char) NULL;
1278 if (!do_int_spell_fix(read_buff_word)) {
1279
1280 close(in_fd[0]);
1281 free(read_buff);
1282 replace_abort();
1283
1284 return TRUE;
1285 }
1286 read_buff_word = read_buff_ptr;
1287 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001288 }
1289
1290 read_buff_ptr++;
1291 }
1292 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001293
1294 close(in_fd[0]);
1295 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001296 replace_abort();
1297
Chris Allegretta271e9722000-11-10 18:15:43 +00001298 /* Process end of spell process */
1299
1300 wait(&spell_status);
1301 if (WIFEXITED(spell_status)) {
1302 if (WEXITSTATUS(spell_status) != 0)
1303 return FALSE;
1304 }
1305 else
1306 return FALSE;
1307
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001308 return TRUE;
1309}
1310#endif
1311
Chris Allegretta7b36c522000-12-06 01:08:10 +00001312#if !defined(NANO_SMALL) && !defined(DISABLE_SPELLER)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001313
1314/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001315int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001316{
Chris Allegretta271e9722000-11-10 18:15:43 +00001317 int alt_spell_status;
1318 pid_t pid_spell;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001319
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001320 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001321
Chris Allegretta271e9722000-11-10 18:15:43 +00001322 /* Start a new process for the alternate speller */
1323
1324 if ( (pid_spell = fork()) == 0) {
1325
1326 /* Start alternate spell program, we are using the PATH here!?!? */
1327 execlp(alt_speller, alt_speller, file_name, NULL);
1328
1329 /* Should not be reached, if alternate speller is found!!! */
1330
1331 exit(1);
1332 }
1333
1334 /* Could not fork?? */
1335
1336 if (pid_spell < 0)
1337 return FALSE;
1338
1339 /* Wait for alternate speller to complete */
1340
1341 wait(&alt_spell_status);
1342 if (WIFEXITED(alt_spell_status)) {
1343 if (WEXITSTATUS(alt_spell_status) != 0)
1344 return FALSE;
1345 }
1346 else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001347 return FALSE;
1348
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001349 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001350 free_filestruct(fileage);
1351 global_init();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001352 open_file(file_name, 0, 1);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001353 edit_update(fileage, CENTER);
Chris Allegretta271e9722000-11-10 18:15:43 +00001354 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001355 set_modified();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001356
1357 return TRUE;
1358}
1359#endif
1360
1361int do_spell(void)
1362{
1363
Chris Allegrettaff269f82000-12-01 18:46:01 +00001364#if defined(NANO_SMALL)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001365 nano_small_msg();
1366 return (TRUE);
Chris Allegretta7b36c522000-12-06 01:08:10 +00001367#elif defined(DISABLE_SPELLER)
Chris Allegrettaff269f82000-12-01 18:46:01 +00001368 nano_disabled_msg();
1369 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001370#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001371 char *temp;
1372 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001373
Chris Allegretta271e9722000-11-10 18:15:43 +00001374 if ((temp = tempnam(0, "nano.")) == NULL) {
1375 statusbar(_("Could not create a temporary filename: %s"),
1376 strerror(errno));
1377 return 0;
1378 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001379
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001380 if (write_file(temp, 1) == -1) {
1381 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001382 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001383 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001384
Chris Allegretta271e9722000-11-10 18:15:43 +00001385 if (alt_speller)
1386 spell_res = do_alt_speller(temp);
1387 else
1388 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001389
Chris Allegretta271e9722000-11-10 18:15:43 +00001390 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001391
1392 if (spell_res)
1393 statusbar(_("Finished checking spelling"));
1394 else
1395 statusbar(_("Spell checking failed"));
1396
1397 return spell_res;
1398
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001399#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001400}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001401
1402int do_exit(void)
1403{
1404 int i;
1405
1406 if (!ISSET(MODIFIED))
1407 finish(0);
1408
Chris Allegretta30885552000-07-14 01:20:12 +00001409 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001410 i = 1;
1411 } else {
1412 i =
1413 do_yesno(0, 0,
1414 _
1415 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1416 }
1417
1418#ifdef DEBUG
1419 dump_buffer(fileage);
1420#endif
1421
1422 if (i == 1) {
1423 if (do_writeout(1) > 0)
1424 finish(0);
1425 } else if (i == 0)
1426 finish(0);
1427 else
1428 statusbar(_("Cancelled"));
1429
1430 display_main_list();
1431 return 1;
1432}
1433
1434#ifndef NANO_SMALL
1435#ifdef NCURSES_MOUSE_VERSION
1436void do_mouse(void)
1437{
1438 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001439 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001440
1441 if (getmouse(&mevent) == ERR)
1442 return;
1443
1444 /* If mouse not in edit window, return (add help selection later). */
1445 if (!wenclose(edit, mevent.y, mevent.x))
1446 return;
1447
1448 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1449 mevent.y -= 2;
1450
1451 /* Selecting where the cursor is sets the mark.
1452 * Selecting beyond the line length with the cursor at the end of the
1453 * line sets the mark as well.
1454 */
1455 if ((mevent.y == current_y) &&
1456 ((mevent.x == current_x) || (current_x == strlen(current->data)
1457 && (mevent.x >
1458 strlen(current->data))))) {
1459 if (ISSET(VIEW_MODE)) {
1460 print_view_warning();
1461 return;
1462 }
1463 do_mark();
1464 } else if (mevent.y > current_y) {
1465 while (mevent.y > current_y) {
1466 if (current->next != NULL)
1467 current = current->next;
1468 else
1469 break;
1470 current_y++;
1471 }
1472 } else if (mevent.y < current_y) {
1473 while (mevent.y < current_y) {
1474 if (current->prev != NULL)
1475 current = current->prev;
1476 else
1477 break;
1478 current_y--;
1479 }
1480 }
1481 current_x = mevent.x;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001482 placewewant = current_x;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001483 while (foo < current_x) {
1484 if (current->data[foo] == NANO_CONTROL_I) {
Chris Allegrettae10debd2000-08-22 01:26:42 +00001485 current_x -= tabsize - (foo % tabsize);
1486 tab_found = 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001487 } else if (current->data[foo] & 0x80);
1488 else if (current->data[foo] < 32)
Chris Allegrettae10debd2000-08-22 01:26:42 +00001489 current_x--;
1490 foo++;
1491 }
1492 /* This is where tab_found comes in. I can't figure out why,
1493 * but without it any line with a tab will place the cursor
1494 * one character behind. Whatever, this fixes it. */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001495 if (tab_found == 1)
Chris Allegrettae10debd2000-08-22 01:26:42 +00001496 current_x++;
1497
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001498 if (current_x > strlen(current->data))
1499 current_x = strlen(current->data);
1500
1501 update_cursor();
1502 edit_refresh();
1503
1504}
1505#endif
1506#endif
1507
1508/* Handler for SIGHUP */
1509RETSIGTYPE handle_hup(int signal)
1510{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001511 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001512}
1513
Chris Allegretta18f8be02000-09-04 03:20:38 +00001514/* What do we do when we catch the suspend signal */
1515RETSIGTYPE do_suspend(int signal)
1516{
1517
1518 act.sa_handler = SIG_DFL;
1519 sigemptyset(&act.sa_mask);
1520 sigaction(SIGTSTP, &act, NULL);
1521
1522 endwin();
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001523 fprintf(stderr, "\n\n\n\n\nUse \"fg\" to return to nano\n");
Chris Allegretta18f8be02000-09-04 03:20:38 +00001524 raise(SIGTSTP);
1525}
1526
1527/* Restore the suspend handler when we come back into the prog */
1528RETSIGTYPE do_cont(int signal)
1529{
1530
1531 act.sa_handler = do_suspend;
1532 sigemptyset(&act.sa_mask);
1533 sigaction(SIGTSTP, &act, NULL);
1534 initscr();
1535 total_refresh();
1536}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001537
1538void handle_sigwinch(int s)
1539{
1540#ifndef NANO_SMALL
1541 char *tty = NULL;
1542 int fd = 0;
1543 int result = 0;
1544 int i = 0;
1545 struct winsize win;
1546
1547 tty = ttyname(0);
1548 if (!tty)
1549 return;
1550 fd = open(tty, O_RDWR);
1551 if (fd == -1)
1552 return;
1553 result = ioctl(fd, TIOCGWINSZ, &win);
1554 if (result == -1)
1555 return;
1556
1557
1558 COLS = win.ws_col;
1559 LINES = win.ws_row;
1560
1561 center_x = COLS / 2;
1562 center_y = LINES / 2;
1563 editwinrows = LINES - 5 + no_help();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001564 fill = COLS - 8;
1565
1566 free(hblank);
1567 hblank = nmalloc(COLS + 1);
1568
1569 for (i = 0; i <= COLS - 1; i++)
1570 hblank[i] = ' ';
1571 hblank[i] = 0;
1572
1573#ifdef HAVE_NCURSES_H
1574 resizeterm(LINES, COLS);
1575#ifdef HAVE_WRESIZE
1576 if (wresize(topwin, 2, COLS) == ERR)
1577 die(_("Cannot resize top win"));
1578 if (mvwin(topwin, 0, 0) == ERR)
1579 die(_("Cannot move top win"));
1580 if (wresize(edit, editwinrows, COLS) == ERR)
1581 die(_("Cannot resize edit win"));
1582 if (mvwin(edit, 2, 0) == ERR)
1583 die(_("Cannot move edit win"));
1584 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1585 die(_("Cannot resize bottom win"));
1586 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1587 die(_("Cannot move bottom win"));
1588#endif /* HAVE_WRESIZE */
1589#endif /* HAVE_NCURSES_H */
1590
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001591 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001592
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001593 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001594 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001595 }
1596 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001597
1598 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001599 refresh();
Chris Allegretta97accc62000-06-19 05:45:52 +00001600 titlebar();
1601 edit_refresh();
1602 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001603 total_refresh();
1604#endif
1605}
1606
Chris Allegretta756f2202000-09-01 13:32:47 +00001607void signal_init(void)
1608{
Chris Allegretta756f2202000-09-01 13:32:47 +00001609
1610 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
1611 memset(&act, 0, sizeof(struct sigaction));
1612 act.sa_handler = SIG_IGN;
1613 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00001614
Chris Allegretta18f8be02000-09-04 03:20:38 +00001615 if (!ISSET(SUSPEND)) {
Chris Allegretta756f2202000-09-01 13:32:47 +00001616 sigaction(SIGTSTP, &act, NULL);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001617 } else {
Chris Allegretta18f8be02000-09-04 03:20:38 +00001618 act.sa_handler = do_suspend;
1619 sigaction(SIGTSTP, &act, NULL);
1620
1621 act.sa_handler = do_cont;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001622 sigaction(SIGCONT, &act, NULL);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001623 }
1624
Chris Allegretta756f2202000-09-01 13:32:47 +00001625
1626 /* Trap SIGHUP cuz we want to write the file out. */
1627 act.sa_handler = handle_hup;
1628 sigaction(SIGHUP, &act, NULL);
1629
1630 act.sa_handler = handle_sigwinch;
1631 sigaction(SIGWINCH, &act, NULL);
1632
1633}
1634
Chris Allegretta2a42af12000-09-12 23:02:49 +00001635void window_init(void)
1636{
Chris Allegretta92c9dd22000-09-13 14:03:27 +00001637 editwinrows = LINES - 5 + no_help();
1638
Chris Allegretta2a42af12000-09-12 23:02:49 +00001639 /* Setup up the main text window */
1640 edit = newwin(editwinrows, COLS, 2, 0);
1641
1642 /* And the other windows */
1643 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001644 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta2a42af12000-09-12 23:02:49 +00001645}
1646
Chris Allegretta756f2202000-09-01 13:32:47 +00001647void mouse_init(void)
1648{
1649#ifndef NANO_SMALL
1650#ifdef NCURSES_MOUSE_VERSION
1651 if (ISSET(USE_MOUSE)) {
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +00001652 keypad_on(TRUE);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00001653
Chris Allegretta756f2202000-09-01 13:32:47 +00001654 mousemask(BUTTON1_RELEASED, NULL);
1655 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00001656
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001657 } else {
Chris Allegretta756f2202000-09-01 13:32:47 +00001658 mousemask(0, NULL);
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +00001659 keypad_on(FALSE);
Chris Allegretta756f2202000-09-01 13:32:47 +00001660 }
1661#endif
1662#endif
1663
1664}
1665
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001666int do_tab(void)
1667{
1668 do_char('\t');
1669 return 1;
1670}
1671
Chris Allegrettaff269f82000-12-01 18:46:01 +00001672#if !defined(NANO_SMALL) && !defined(DISABLE_JUSTIFY)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001673int empty_line(const char *data)
1674{
1675 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001676 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001677 return 0;
1678
1679 data++;
1680 }
1681
1682 return 1;
1683}
1684
1685int no_spaces(const char *data)
1686{
1687 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001688 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001689 return 0;
1690
1691 data++;
1692 }
1693
1694 return 1;
1695}
1696
1697void justify_format(char *data)
1698{
1699 int i = 0;
1700 int len = strlen(data);
1701
1702 /* Skip first character regardless and leading whitespace. */
1703 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001704 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001705 break;
1706 }
1707
1708 i++; /* (i) is now at least 2. */
1709
1710 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
1711 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001712 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001713 && (data[i - 2] != '.')) {
1714 memmove(data + i, data + i + 1, len - i);
1715 len--;
1716 i--;
1717 }
1718 }
1719}
1720#endif
1721
1722int do_justify(void)
1723{
Chris Allegrettaff269f82000-12-01 18:46:01 +00001724#ifdef NANO_SMALL
1725 nano_small_msg();
1726 return 1;
1727#elif defined(DISABLE_JUSTIFY)
1728 nano_disabled_msg();
1729 return 1;
1730#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001731 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta9149e612000-11-27 00:23:41 +00001732 int initial_y, kbinput;
1733 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001734
1735 if (empty_line(current->data)) {
1736 /* Justify starting at first non-empty line. */
1737 do {
1738 if (!current->next)
1739 return 1;
1740
1741 current = current->next;
1742 current_y++;
1743 }
1744 while (empty_line(current->data));
1745 } else {
1746 /* Search back for the beginning of the paragraph, where
1747 * Paragraph is 1) A line with leading whitespace
1748 * or 2) A line following an empty line.
1749 */
1750 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001751 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001752 break;
1753
1754 current = current->prev;
1755 current_y--;
1756 }
1757
1758 /* First line with leading whitespace may be empty. */
1759 if (empty_line(current->data)) {
1760 if (current->next) {
1761 current = current->next;
1762 current_y++;
1763 } else
1764 return 1;
1765 }
1766 }
1767 initial = current;
1768 initial_y = current_y;
1769
1770 set_modified();
Chris Allegretta9149e612000-11-27 00:23:41 +00001771 cutbak = cutbuffer; /* Got to like cutbak ;) */
1772 cutbuffer = NULL;
1773
1774 tmptop = current;
1775 tmpjust = copy_node(current);
1776 add_to_cutbuffer(tmpjust);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001777 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001778 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001779 && current->next->data[0]) {
1780 filestruct *tmpnode = current->next;
1781 int len = strlen(current->data);
1782 int len2 = strlen(current->next->data);
1783
Chris Allegretta9149e612000-11-27 00:23:41 +00001784 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00001785 tmpjust = copy_node(current->next);
1786 add_to_cutbuffer(tmpjust);
1787
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001788 /* length of both strings plus space between strings and ending \0. */
1789 current->data = nrealloc(current->data, len + len2 + 2);
1790 current->data[len++] = ' ';
1791 current->data[len] = '\0';
1792
1793 strncat(current->data, current->next->data, len2);
1794
1795 unlink_node(tmpnode);
1796 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001797 }
1798
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001799 totsize -= strlen(current->data);
1800
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001801 justify_format(current->data);
1802
1803 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001804 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001805
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001806 if ((strlenpt(current->data) > (fill))
1807 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001808 do {
1809 int i = 0;
1810 int len2 = 0;
1811 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001812
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001813 /* Start at fill , unless line isn't that long (but it
1814 * appears at least fill long with tabs.
1815 */
1816 if (slen > fill)
1817 i = fill;
1818 else
1819 i = slen;
1820 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001821 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001822 ((strlenpt(current->data) - strlen(current->data + i))
1823 <= fill))
1824 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001825 }
1826 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001827 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001828
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001829 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001830
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001831 len2 = strlen(current->data + i + 1);
1832 tmpline->data = nmalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001833
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001834 /* Skip the white space in current. */
1835 memcpy(tmpline->data, current->data + i + 1, len2);
1836 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001837
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001838 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001839
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001840 tmpline->prev = current;
1841 tmpline->next = current->next;
1842 if (current->next != NULL)
1843 current->next->prev = tmpline;
1844
1845 current->next = tmpline;
1846 current = tmpline;
1847 slen -= i + 1;
1848 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001849 } while ((strlenpt(current->data) > (fill))
1850 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001851 }
Chris Allegretta9149e612000-11-27 00:23:41 +00001852 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001853
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001854 if (current->next)
1855 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00001856 else
1857 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001858 current_x = 0;
1859 placewewant = 0;
1860
Adam Rogoyski09f97962000-06-20 02:50:33 +00001861 renumber(initial);
1862 totlines = filebot->lineno;
1863
1864 werase(edit);
1865
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001866 if ((current_y < 0) || (current_y >= editwinrows - 1)
1867 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001868 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001869 center_cursor();
1870 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001871 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001872 }
1873
Adam Rogoyski09f97962000-06-20 02:50:33 +00001874 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00001875 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00001876 /* Change the shortcut list to display the unjustify code */
1877 shortcut_init(1);
1878 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00001879 reset_cursor();
1880
Chris Allegretta07798352000-11-27 22:58:23 +00001881 /* Now get a keystroke and see if it's unjustify, if not unget the keytroke
Chris Allegretta9149e612000-11-27 00:23:41 +00001882 and return */
Chris Allegretta4a9c8582000-11-27 22:59:40 +00001883 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY)
Chris Allegretta07798352000-11-27 22:58:23 +00001884 ungetch(kbinput);
Chris Allegretta9149e612000-11-27 00:23:41 +00001885 else {
1886 /* Else restore the justify we just did (ungrateful user!) */
1887 if (tmptop->prev != NULL)
1888 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00001889 else
1890 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00001891 tmpbot->next->prev = tmptop->prev;
1892 current = tmpbot->next;
1893 tmpbot->next = NULL;
1894 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00001895 if (tmptop->prev == NULL)
1896 edit_refresh();
1897
Chris Allegretta9149e612000-11-27 00:23:41 +00001898 free_filestruct(tmptop);
1899 blank_statusbar_refresh();
1900 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00001901 shortcut_init(0);
1902 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00001903 free_filestruct(cutbuffer);
1904 cutbuffer = cutbak;
1905
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001906 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001907#endif
1908}
1909
Chris Allegretta3bc8c722000-12-10 17:03:25 +00001910#if !defined(NANO_SMALL) && !defined(DISABLE_HELP)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001911void help_init(void)
1912{
1913 int i, sofar = 0;
1914 long allocsize = 1; /* How much space we're gonna need for the help text */
1915 char buf[BUFSIZ];
1916
1917 /* Compute the space needed for the shortcut lists - we add 15 to
1918 have room for the shortcut abbrev and its possible alternate keys */
1919 for (i = 0; i < MAIN_LIST_LEN; i++)
1920 if (main_list[i].help != NULL)
1921 allocsize += strlen(main_list[i].help) + 15;
1922
Chris Allegretta756f2202000-09-01 13:32:47 +00001923 /* And for the toggle list, we also allocate space for extra text. */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00001924 for (i = 0; i <= TOGGLE_LEN - 1; i++)
Chris Allegretta756f2202000-09-01 13:32:47 +00001925 if (toggles[i].desc != NULL)
1926 allocsize += strlen(toggles[i].desc) + 30;
1927
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001928 allocsize += strlen(help_text_init);
1929
1930 if (help_text != NULL)
1931 free(help_text);
1932
1933 /* Allocate space for the help text */
1934 help_text = nmalloc(allocsize);
1935
1936 /* Now add the text we want */
1937 strcpy(help_text, help_text_init);
1938
1939 /* Now add our shortcut info */
Chris Allegretta756f2202000-09-01 13:32:47 +00001940 for (i = 0; i < MAIN_LIST_LEN - 1; i++) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001941 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001942
1943 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00001944 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001945 main_list[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001946 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001947 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001948
1949 if (main_list[i].altval > 0)
Chris Allegrettae49f1232000-09-02 07:20:39 +00001950 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001951 main_list[i].altval - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001952 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001953 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001954
Chris Allegretta756f2202000-09-01 13:32:47 +00001955
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001956 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00001957 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001958
Chris Allegretta756f2202000-09-01 13:32:47 +00001959
1960 strcat(help_text, buf);
1961 strcat(help_text, "\n");
1962 }
1963
1964 /* And the toggles... */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00001965 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001966 sofar = snprintf(buf, BUFSIZ,
1967 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00001968
1969 if (toggles[i].desc != NULL)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001970 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
1971 toggles[i].desc);
Chris Allegretta756f2202000-09-01 13:32:47 +00001972
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001973 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00001974 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001975 }
1976
1977}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00001978#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001979
Chris Allegretta756f2202000-09-01 13:32:47 +00001980void do_toggle(int which)
1981{
1982#ifndef NANO_SMALL
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00001983 char *enabled = _("enabled");
1984 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00001985
Chris Allegretta2a42af12000-09-12 23:02:49 +00001986 if (ISSET(toggles[which].flag))
Chris Allegretta756f2202000-09-01 13:32:47 +00001987 UNSET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00001988 else
Chris Allegretta756f2202000-09-01 13:32:47 +00001989 SET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00001990
Chris Allegretta756f2202000-09-01 13:32:47 +00001991 switch (toggles[which].val) {
1992 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00001993 shortcut_init(0);
Chris Allegretta756f2202000-09-01 13:32:47 +00001994 display_main_list();
1995 break;
1996 case TOGGLE_SUSPEND_KEY:
1997 signal_init();
1998 break;
1999 case TOGGLE_MOUSE_KEY:
2000 mouse_init();
2001 break;
2002 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002003 wclear(bottomwin);
2004 wrefresh(bottomwin);
2005 window_init();
2006 edit_refresh();
2007 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002008 break;
2009 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002010
2011 if (!ISSET(toggles[which].flag)) {
2012 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002013 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002014 statusbar("%s %s", toggles[which].desc, enabled);
2015 else
2016 statusbar("%s %s", toggles[which].desc, disabled);
2017 } else {
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, disabled);
2021 else
2022 statusbar("%s %s", toggles[which].desc, enabled);
2023 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002024 SET(DISABLE_CURPOS);
2025
Chris Allegretta4c780be2000-09-01 17:59:18 +00002026#else
2027 nano_small_msg();
Chris Allegretta756f2202000-09-01 13:32:47 +00002028#endif
2029}
2030
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002031int main(int argc, char *argv[])
2032{
2033 int optchr;
2034 int kbinput; /* Input from keyboard */
2035 long startline = 0; /* Line to try and start at */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002036 int keyhandled = 0; /* Have we handled the keystroke yet? */
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002037 int i, modify_control_seq = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002038 char *argv0;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002039#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002040 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002041#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002042
2043#ifdef HAVE_GETOPT_LONG
2044 int option_index = 0;
2045 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002046#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002047 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002048#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002049 {"version", 0, 0, 'V'},
2050 {"const", 0, 0, 'c'},
2051 {"suspend", 0, 0, 'z'},
2052 {"nowrap", 0, 0, 'w'},
2053 {"nohelp", 0, 0, 'x'},
2054 {"help", 0, 0, 'h'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002055#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002056 {"cut", 0, 0, 'k'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002057#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002058 {"autoindent", 0, 0, 'i'},
2059 {"tempfile", 0, 0, 't'},
2060 {"speller", 1, 0, 's'},
2061 {"fill", 1, 0, 'r'},
2062 {"mouse", 0, 0, 'm'},
2063 {"pico", 0, 0, 'p'},
2064 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002065 {"tabsize", 1, 0, 'T'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002066 {0, 0, 0, 0}
2067 };
2068#endif
2069
2070 /* Flag inits... */
2071 SET(FOLLOW_SYMLINKS);
2072
2073#ifndef NANO_SMALL
2074 setlocale(LC_ALL, "");
2075 bindtextdomain(PACKAGE, LOCALEDIR);
2076 textdomain(PACKAGE);
2077#endif
2078
2079#ifdef HAVE_GETOPT_LONG
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002080 while ((optchr = getopt_long(argc, argv, "?T:RVbcefhiklmpr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002081 long_options, &option_index)) != EOF) {
2082#else
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002083 while ((optchr = getopt(argc, argv, "h?T:RVbcefiklmpr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002084#endif
2085
2086 switch (optchr) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002087 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002088 tabsize = atoi(optarg);
2089 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002090 usage(); /* To stop bogus data for tab width */
2091 finish(1);
2092 }
2093 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002094#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002095 case 'R':
2096 SET(USE_REGEXP);
2097 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002098#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002099 case 'V':
2100 version();
2101 exit(0);
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002102 case 'b':
2103 case 'e':
2104 case 'f':
2105 /* Pico compatibility flags */
2106 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002107 case 'c':
2108 SET(CONSTUPDATE);
2109 break;
2110 case 'h':
2111 case '?':
2112 usage();
2113 exit(0);
2114 case 'i':
2115 SET(AUTOINDENT);
2116 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002117#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002118 case 'k':
2119 SET(CUT_TO_END);
2120 break;
Chris Allegretta18bd0292000-07-28 01:18:10 +00002121#else
2122 case 'k':
2123 usage(); /* Oops! You dont really have that option */
2124 finish(1);
Chris Allegrettad19e9912000-07-12 18:14:51 +00002125#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002126 case 'l':
2127 UNSET(FOLLOW_SYMLINKS);
2128 break;
2129 case 'm':
2130 SET(USE_MOUSE);
2131 break;
2132 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002133 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002134 break;
2135 case 'r':
2136 fill = atoi(optarg);
2137 if (fill <= 0) {
2138 usage(); /* To stop bogus data (like a string) */
2139 finish(1);
2140 }
2141 break;
2142 case 's':
2143 alt_speller = nmalloc(strlen(optarg) + 1);
2144 strcpy(alt_speller, optarg);
2145 break;
2146 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002147 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002148 break;
2149 case 'v':
2150 SET(VIEW_MODE);
2151 break;
2152 case 'w':
2153 SET(NO_WRAP);
2154 break;
2155 case 'x':
2156 SET(NO_HELP);
2157 break;
2158 case 'z':
2159 SET(SUSPEND);
2160 break;
2161 default:
2162 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002163 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002164 }
2165
2166 }
2167
2168 argv0 = strrchr(argv[0], '/');
2169 if ((argv0 && strstr(argv0, "pico"))
2170 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002171 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002172
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002173 /* See if there's a non-option in argv (first non-option is the
2174 filename, if +LINE is not given) */
2175 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002176 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002177 else {
2178 /* Look for the +line flag... */
2179 if (argv[optind][0] == '+') {
2180 startline = atoi(&argv[optind][1]);
2181 optind++;
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
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002185 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002186
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002187 } else
2188 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002189 }
2190
2191
2192 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002193 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002194
Chris Allegretta9239d742000-09-06 15:19:18 +00002195#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002196 term = oldterm;
2197 term.c_cc[VINTR] = _POSIX_VDISABLE;
2198 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2199 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002200 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002201#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002202
2203 /* now ncurses init stuff... */
2204 initscr();
2205 savetty();
2206 nonl();
2207 cbreak();
2208 noecho();
2209 timeout(0);
2210
2211 /* Set up some global variables */
2212 global_init();
Chris Allegretta07798352000-11-27 22:58:23 +00002213 shortcut_init(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002214 init_help_msg();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002215#if !defined(NANO_SMALL) && !defined(DISABLE_HELP)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002216 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002217#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002218 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002219
2220#ifdef DEBUG
2221 fprintf(stderr, _("Main: set up windows\n"));
2222#endif
2223
Chris Allegretta2a42af12000-09-12 23:02:49 +00002224 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002225 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002226
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002227#ifdef PDCURSES
2228 /* Must have this for the arrow, et al, keys to even work in
2229 PDCurses+cygwin under Windows */
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +00002230 keypad_on(TRUE);
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002231#endif
2232
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002233#ifdef DEBUG
2234 fprintf(stderr, _("Main: bottom win\n"));
2235#endif
2236 /* Set up up bottom of window */
2237 display_main_list();
2238
2239#ifdef DEBUG
2240 fprintf(stderr, _("Main: open file\n"));
2241#endif
2242
2243 titlebar();
Chris Allegretta31c76662000-11-21 06:20:20 +00002244
2245 /* Now we check to see if argv[optind] is non-null to determine if
2246 we're dealing with a new file or not, not argc == 1... */
2247 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002248 new_file();
2249 else
2250 open_file(filename, 0, 0);
2251
2252 if (startline > 0)
2253 do_gotoline(startline);
2254 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002255 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002256
Robert Siemborski6967eec2000-07-08 14:23:32 +00002257 edit_refresh();
2258 reset_cursor();
2259
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002260 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00002261
2262#ifndef _POSIX_VDISABLE
2263 /* We're going to have to do it the old way, i.e. on cygwin */
2264 raw();
2265#endif
2266
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002267 kbinput = wgetch(edit);
2268 if (kbinput == 27) { /* Grab Alt-key stuff first */
2269 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002270 /* Alt-O, suddenly very important ;) */
Chris Allegretta16e41682000-09-11 22:33:54 +00002271 case 79:
2272 kbinput = wgetch(edit);
2273 if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002274 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002275#ifdef DEBUG
2276 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002277 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2278 kbinput, kbinput);
2279 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002280 }
2281#endif
2282 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002283 case 27:
2284 /* If we get Alt-Alt, the next keystroke should be the same as a
2285 control sequence */
2286 modify_control_seq = 1;
2287 keyhandled = 1;
2288 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002289 case 91:
2290
2291 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002292 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00002293 kbinput = wgetch(edit);
2294 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002295 kbinput = KEY_F(kbinput - 48);
2296 wgetch(edit);
2297 } else if (kbinput >= '7' && kbinput <= '9') {
2298 kbinput = KEY_F(kbinput - 49);
2299 wgetch(edit);
2300 } else if (kbinput == 126)
2301 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00002302
2303#ifdef DEBUG
2304 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002305 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
2306 kbinput, kbinput);
2307 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002308 }
2309#endif
2310
2311 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002312 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00002313 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00002314 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002315 case '0':
2316 kbinput = KEY_F(9);
2317 wgetch(edit);
2318 break;
2319 case '1':
2320 kbinput = KEY_F(10);
2321 wgetch(edit);
2322 break;
2323 case '3':
2324 kbinput = KEY_F(11);
2325 wgetch(edit);
2326 break;
2327 case '4':
2328 kbinput = KEY_F(12);
2329 wgetch(edit);
2330 break;
2331 case 126: /* Hack, make insert key do something
2332 usefile, like insert file */
2333 do_insertfile();
2334 keyhandled = 1;
2335 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002336#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002337 default:
2338 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
2339 kbinput, kbinput);
2340 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002341#endif
2342
2343 }
2344 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002345 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002346 kbinput = NANO_DELETE_KEY;
2347 wgetch(edit);
2348 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002349 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002350 kbinput = NANO_END_KEY;
2351 wgetch(edit);
2352 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002353 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00002354 kbinput = KEY_PPAGE;
2355 wgetch(edit);
2356 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002357 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00002358 kbinput = KEY_NPAGE;
2359 wgetch(edit);
2360 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002361 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00002362 kbinput = wgetch(edit);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002363 if (kbinput >= 'A' && kbinput <= 'E')
2364 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00002365 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002366 case 'A':
2367 kbinput = KEY_UP;
2368 break;
2369 case 'B':
2370 kbinput = KEY_DOWN;
2371 break;
2372 case 'C':
2373 kbinput = KEY_RIGHT;
2374 break;
2375 case 'D':
2376 kbinput = KEY_LEFT;
2377 break;
2378 case 'H':
2379 kbinput = KEY_HOME;
2380 break;
2381 case 'F':
2382 kbinput = KEY_END;
2383 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002384 default:
2385#ifdef DEBUG
2386 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
2387 kbinput, kbinput);
2388#endif
2389 break;
2390 }
2391 break;
2392 default:
2393
2394 /* Check for the altkey defs.... */
2395 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
2396 if (kbinput == main_list[i].altval ||
2397 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002398 kbinput = main_list[i].val;
2399 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002400 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002401#ifndef NANO_SMALL
2402 /* And for toggle switches */
2403 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
2404 if (kbinput == toggles[i].val ||
2405 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002406 do_toggle(i);
2407 keyhandled = 1;
2408 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002409 }
2410#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002411#ifdef DEBUG
2412 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
2413 kbinput);
2414#endif
2415 break;
2416 }
2417 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002418 /* If the modify_control_seq is set, we received an Alt-Alt
2419 sequence before this, so we make this key a control sequence
2420 by subtracting 64 or 96, depending on its value. */
2421 if (!keyhandled && modify_control_seq) {
2422 if (kbinput >= 'A' && kbinput < 'a')
2423 kbinput -= 64;
2424 else if (kbinput >= 'a' && kbinput <= 'z')
2425 kbinput -= 96;
2426
2427 modify_control_seq = 0;
2428 }
2429
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002430 /* Look through the main shortcut list to see if we've hit a
2431 shortcut key */
Chris Allegretta756f2202000-09-01 13:32:47 +00002432 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002433 if (kbinput == main_list[i].val ||
2434 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
2435 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
2436 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
2437 print_view_warning();
2438 else
2439 main_list[i].func();
2440 keyhandled = 1;
2441 }
2442 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002443 /* If we're in raw mode or using Alt-Alt-x, we have to catch
2444 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00002445 if (kbinput == 17 || kbinput == 19)
2446 keyhandled = 1;
2447
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002448 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00002449 if (kbinput == 26) {
2450 if (ISSET(SUSPEND))
2451 do_suspend(0);
2452 keyhandled = 1;
2453 }
Chris Allegretta9239d742000-09-06 15:19:18 +00002454
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002455 /* Last gasp, stuff that's not in the main lists */
2456 if (!keyhandled)
2457 switch (kbinput) {
2458#ifndef NANO_SMALL
2459#ifdef NCURSES_MOUSE_VERSION
2460 case KEY_MOUSE:
2461 do_mouse();
2462 break;
2463#endif
2464#endif
2465 case 0: /* Erg */
2466 do_next_word();
2467 break;
2468 case 331: /* Stuff that we don't want to do squat */
2469 case -1:
2470 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002471#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002472 case 541: /* ???? */
2473 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00002474 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002475 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00002476 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002477#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002478
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002479 break;
2480 default:
2481#ifdef DEBUG
2482 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
2483#endif
2484 /* We no longer stop unhandled sequences so that people with
2485 odd character sets can type... */
2486
2487 if (ISSET(VIEW_MODE)) {
2488 print_view_warning();
2489 break;
2490 }
2491 do_char(kbinput);
2492 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002493 if (ISSET(CONSTUPDATE)) {
2494 if (ISSET(DISABLE_CURPOS))
2495 UNSET(DISABLE_CURPOS);
2496 else
2497 do_cursorpos();
2498 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002499
2500 reset_cursor();
2501 wrefresh(edit);
2502 keyhandled = 0;
2503 }
2504
2505 getchar();
2506 finish(0);
2507
2508}