blob: d6b43bf5c00dc28e96bf585de5c4dd410b60301d [file] [log] [blame]
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001/**************************************************************************
2 * nano.c *
3 * *
4 * Copyright (C) 1999 Chris Allegretta *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 1, or (at your option) *
8 * any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
18 * *
19 **************************************************************************/
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <stdarg.h>
24#include <signal.h>
25#include <unistd.h>
26#include <string.h>
27#include <fcntl.h>
28#include <sys/stat.h>
29#include <sys/ioctl.h>
30#include <sys/param.h>
31#include <errno.h>
32#include <ctype.h>
33#include <locale.h>
34#include <limits.h>
Adam Rogoyski77f36de2000-06-07 03:56:54 +000035#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000036
37#include "config.h"
38#include "proto.h"
39#include "nano.h"
40
41#ifndef NANO_SMALL
42#include <libintl.h>
43#define _(string) gettext(string)
44#else
45#define _(string) (string)
46#endif
47
48#ifdef HAVE_TERMIOS_H
49#include <termios.h>
50#endif
51
52#ifdef HAVE_TERMIO_H
53#include <termio.h>
54#endif
55
56#ifdef HAVE_GETOPT_H
57#include <getopt.h>
58#endif
59
60/* Former globals, now static */
61char *last_search; /* Last string we searched for */
62char *last_replace; /* Last replacement string */
63int temp_opt = 0; /* Editing temp file (pico -t option) */
64int 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 */
69
70/* What we do when we're all set to exit */
71RETSIGTYPE finish(int sigage)
72{
73 if (!ISSET(NO_HELP)) {
74 mvwaddstr(bottomwin, 1, 0, hblank);
75 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000076 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000077 mvwaddstr(bottomwin, 0, 0, hblank);
78
79 wrefresh(bottomwin);
80 endwin();
81
82 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +000083 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000084
85 exit(sigage);
86}
87
88/* Die (gracefully?) */
89void die(char *msg, ...)
90{
91 va_list ap;
92
93 va_start(ap, msg);
94 vfprintf(stderr, msg, ap);
95 va_end(ap);
96
97 /* if we can't save we have REAL bad problems,
98 * but we might as well TRY. FIXME: This should probabally base it
99 * off of the current filename */
100 write_file("nano.save", 0);
101
102 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000103 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000104
105 clear();
106 refresh();
107 resetty();
108 endwin();
109
110 fprintf(stderr, msg);
111 fprintf(stderr, _("\nBuffer written to 'nano.save'\n"));
112
113 exit(1); /* We have a problem: exit w/ errorlevel(1) */
114}
115
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000116void print_view_warning(void)
117{
118 statusbar(_("Key illegal in VIEW mode"));
119}
120
121/* Initialize global variables - no better way for now */
122void global_init(void)
123{
124 int i;
125
126 center_x = COLS / 2;
127 center_y = LINES / 2;
128 current_x = 0;
129 current_y = 0;
130 editwinrows = LINES - 5 + no_help();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000131 fileage = NULL;
132 cutbuffer = NULL;
133 current = NULL;
134 edittop = NULL;
135 editbot = NULL;
136 totlines = 0;
137 placewewant = 0;
138 if (!fill)
139 fill = COLS - 8;
140 hblank = nmalloc(COLS + 1);
141
142 /* Thanks BG for this bit... */
143 for (i = 0; i <= COLS - 1; i++)
144 hblank[i] = ' ';
145 hblank[i] = 0;
146 last_search = nmalloc(132);
147 last_replace = nmalloc(132);
148 answer = nmalloc(132);
149
150}
151
152void init_help_msg(void)
153{
154
155#ifndef NANO_SMALL
156
157 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000158 _(" nano help text\n\n "
159 "The nano editor is designed to emulate the functionality and "
160 "ease-of-use of the UW Pico text editor. There are four main "
161 "sections of the editor: The top line shows the program "
162 "version, the current filename being edited, and whether "
163 "or not the file has been modified. Next is the main editor "
164 "window showing the file being edited. The status line is "
165 "the third line from the bottom and shows important messages. "
166 "The bottom two lines show the most commonly used shortcuts "
167 "in the editor.\n\n "
168 "The notation for shortcuts is as follows: Control-key "
169 "sequences are notated with a caret (^) symbol. Alt-key "
170 "sequences are notated with an at (@) symbol. The following "
171 "keystrokes are available in the main editor window. "
172 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000173#endif
174
175}
176
177/* Make a copy of a node to a pointer (space will be malloc()ed) */
178filestruct *copy_node(filestruct * src)
179{
180 filestruct *dst;
181
182 dst = nmalloc(sizeof(filestruct));
183 dst->data = nmalloc(strlen(src->data) + 1);
184
185 dst->next = src->next;
186 dst->prev = src->prev;
187
188 strcpy(dst->data, src->data);
189 dst->lineno = src->lineno;
190
191 return dst;
192}
193
194/* Unlink a node from the rest of the struct */
195void unlink_node(filestruct * fileptr)
196{
197 if (fileptr->prev != NULL)
198 fileptr->prev->next = fileptr->next;
199
200 if (fileptr->next != NULL)
201 fileptr->next->prev = fileptr->prev;
202}
203
204void delete_node(filestruct * fileptr)
205{
206 if (fileptr->data != NULL)
207 free(fileptr->data);
208 free(fileptr);
209}
210
211/* Okay, now let's duplicate a whole struct! */
212filestruct *copy_filestruct(filestruct * src)
213{
214 filestruct *dst, *tmp, *head, *prev;
215
216 head = copy_node(src);
217 dst = head; /* Else we barf on copying just one line */
218 head->prev = NULL;
219 tmp = src->next;
220 prev = head;
221
222 while (tmp != NULL) {
223 dst = copy_node(tmp);
224 dst->prev = prev;
225 prev->next = dst;
226
227 prev = dst;
228 tmp = tmp->next;
229 }
230
231 dst->next = NULL;
232 return head;
233}
234
235/* Free() a single node */
236int free_node(filestruct * src)
237{
238 if (src == NULL)
239 return 0;
240
241 if (src->next != NULL)
242 free(src->data);
243 free(src);
244 return 1;
245}
246
247int free_filestruct(filestruct * src)
248{
249 filestruct *fileptr = src;
250
251 if (src == NULL)
252 return 0;
253
254 while (fileptr->next != NULL) {
255 fileptr = fileptr->next;
256 free_node(fileptr->prev);
257
258#ifdef DEBUG
259 fprintf(stderr, _("free_node(): free'd a node, YAY!\n"));
260#endif
261 }
262 free_node(fileptr);
263#ifdef DEBUG
264 fprintf(stderr, _("free_node(): free'd last node.\n"));
265#endif
266
267 return 1;
268}
269
270int renumber_all(void)
271{
272 filestruct *temp;
273 long i = 1;
274
275 for (temp = fileage; temp != NULL; temp = temp->next) {
276 temp->lineno = i++;
277 }
278
279 return 0;
280}
281
282int renumber(filestruct * fileptr)
283{
284 filestruct *temp;
285
286 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
287 renumber_all();
288 return 0;
289 }
290 for (temp = fileptr; temp != NULL; temp = temp->next) {
291 temp->lineno = temp->prev->lineno + 1;
292 }
293
294 return 0;
295}
296
297/* Fix the memory allocation for a string */
298void align(char **strp)
299{
300 /* There was a serious bug here: the new address was never
301 stored anywhere... */
302
303 *strp = nrealloc(*strp, strlen(*strp) + 1);
304}
305
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000306void usage(void)
307{
308#ifdef HAVE_GETOPT_LONG
309 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
310 printf(_("Option Long option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000311#ifdef HAVE_TABSIZE
312 printf(_
313 (" -T --tabsize=[num] Set width of a tab to num\n"));
314#endif
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000315 printf(_
316 (" -R --regexp Use regular expressions for search\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000317 printf
318 (_
319 (" -V --version Print version information and exit\n"));
320 printf(_
321 (" -c --const Constantly show cursor position\n"));
322 printf(_
323 (" -h --help Show this message\n"));
324 printf(_
325 (" -i --autoindent Automatically indent new lines\n"));
326 printf(_
327 (" -l --nofollow Don't follow symbolic links, overwrite.\n"));
328#ifndef NANO_SMALL
329#ifdef NCURSES_MOUSE_VERSION
330 printf(_(" -m --mouse Enable mouse\n"));
331#endif
332#endif
333 printf
334 (_
335 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
336 printf(_
337 (" -p --pico Make bottom 2 lines more Pico-like\n"));
338 printf(_
339 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
340 printf(_
341 (" -t --tempfile Auto save on exit, don't prompt\n"));
342 printf(_
343 (" -v --view View (read only) mode\n"));
344 printf(_
345 (" -w --nowrap Don't wrap long lines\n"));
346 printf(_
347 (" -x --nohelp Don't show help window\n"));
348 printf(_
349 (" -z --suspend Enable suspend\n"));
350 printf(_
351 (" +LINE Start at line number LINE\n"));
352#else
353 printf(_("Usage: nano [option] +LINE <file>\n\n"));
354 printf(_("Option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000355#ifdef HAVE_TABSIZE
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000356 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000357#endif
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000358 printf(_(" -R Use regular expressions for search\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000359 printf(_(" -V Print version information and exit\n"));
360 printf(_(" -c Constantly show cursor position\n"));
361 printf(_(" -h Show this message\n"));
362 printf(_(" -i Automatically indent new lines\n"));
363 printf(_
364 (" -l Don't follow symbolic links, overwrite.\n"));
365#ifndef NANO_SMALL
366#ifdef NCURSES_MOUSE_VERSION
367 printf(_(" -m Enable mouse\n"));
368#endif
369#endif
370 printf(_
371 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
372 printf(_(" -s [prog] Enable alternate speller\n"));
373 printf(_(" -p Make bottom 2 lines more Pico-like\n"));
374 printf(_(" -t Auto save on exit, don't prompt\n"));
375 printf(_(" -v View (read only) mode\n"));
376 printf(_(" -w Don't wrap long lines\n"));
377 printf(_(" -x Don't show help window\n"));
378 printf(_(" -z Enable suspend\n"));
379 printf(_(" +LINE Start at line number LINE\n"));
380#endif
381 exit(0);
382}
383
384void version(void)
385{
386 printf(_(" nano version %s by Chris Allegretta (compiled %s, %s)\n"),
387 VERSION, __TIME__, __DATE__);
388 printf(_(" Email: nano@asty.org Web: http://www.asty.org/nano\n"));
389}
390
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000391filestruct *make_new_node(filestruct * prevnode)
392{
393 filestruct *newnode;
394
395 newnode = nmalloc(sizeof(filestruct));
396 newnode->data = NULL;
397
398 newnode->prev = prevnode;
399 newnode->next = NULL;
400
401 if (prevnode != NULL)
402 newnode->lineno = prevnode->lineno + 1;
403
404 return newnode;
405}
406
407int do_mark()
408{
409#ifdef NANO_SMALL
410 nano_small_msg();
411#else
412 if (!ISSET(MARK_ISSET)) {
413 statusbar(_("Mark Set"));
414 SET(MARK_ISSET);
415 mark_beginbuf = current;
416 mark_beginx = current_x;
417 } else {
418 statusbar(_("Mark UNset"));
419 UNSET(MARK_ISSET);
420 mark_beginbuf = NULL;
421 mark_beginx = 0;
422
423 edit_refresh();
424 }
425#endif
426 return 1;
427}
428
429int no_help(void)
430{
431 if ISSET
432 (NO_HELP)
433 return 2;
434 else
435 return 0;
436}
437
438void nano_small_msg(void)
439{
440 statusbar("Sorry, this function not available with nano-tiny option");
441}
442
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000443/* The user typed a printable character; add it to the edit buffer */
444void do_char(char ch)
445{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000446 /* magic-line: when a character is inserted on the current magic line,
447 * it means we need a new one! */
448 if(filebot == current && current->data[0] == '\0') {
449 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000450 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000451 }
452
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000453 /* More dangerousness fun =) */
454 current->data = nrealloc(current->data, strlen(current->data) + 2);
455 memmove(&current->data[current_x + 1],
456 &current->data[current_x],
457 strlen(current->data) - current_x + 1);
458 current->data[current_x] = ch;
459 do_right();
460
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000461 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000462 check_wrap(current, ch);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000463 set_modified();
464 check_statblank();
465 UNSET(KEEP_CUTBUFFER);
466 totsize++;
467
468}
469
470/* Someone hits return *gasp!* */
471int do_enter(filestruct * inptr)
472{
473 filestruct *new;
474 char *tmp, *spc;
475 int extra = 0;
476
477 new = make_new_node(inptr);
478 tmp = &current->data[current_x];
479 current_x = 0;
480
481 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
482 if (ISSET(AUTOINDENT)) {
483 spc = current->data;
484 if (spc) {
485 while ((*spc == ' ') || (*spc == '\t')) {
486 extra++;
487 spc++;
488 current_x++;
489 }
490 new->data = nmalloc(strlen(tmp) + extra + 1);
491 strncpy(new->data, current->data, extra);
492 strcpy(&new->data[extra], tmp);
493 }
494 } else {
495 new->data = nmalloc(strlen(tmp) + 1);
496 strcpy(new->data, tmp);
497 }
498 *tmp = 0;
499
500 new->next = inptr->next;
501 new->prev = inptr;
502 inptr->next = new;
503 if (new->next != NULL)
504 new->next->prev = new;
505 else {
506 filebot = new;
507 editbot = new;
508 }
509
510 totsize++;
511 renumber(current);
512 current = new;
513 align(&current->data);
514
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000515 /* The logic here is as follows:
516 * -> If we are at the bottom of the buffer, we want to recenter
517 * (read: rebuild) the screen and forcably move the cursor.
518 * -> otherwise, we want simply to redraw the screen and update
519 * where we think the cursor is.
520 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000521 if (current_y == editwinrows - 1) {
522 edit_update(current);
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000523 reset_cursor();
524 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000525 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000526 edit_refresh();
527 update_cursor();
528 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000529
530 totlines++;
531 set_modified();
532
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000533 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000534 return 1;
535}
536
537int do_enter_void(void)
538{
539 return do_enter(current);
540}
541
542void do_next_word(void)
543{
544 filestruct *fileptr;
545 int i;
546
547 if (current == NULL)
548 return;
549
550 i = current_x;
551 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
552 if (fileptr == current) {
553 while (isalnum((int) fileptr->data[i])
554 && fileptr->data[i] != 0)
555 i++;
556
557 if (fileptr->data[i] == 0) {
558 i = 0;
559 continue;
560 }
561 }
562 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
563 i++;
564
565 if (fileptr->data[i] != 0)
566 break;
567
568 i = 0;
569 }
570 if (fileptr == NULL)
571 current = filebot;
572 else
573 current = fileptr;
574
575 current_x = i;
576 placewewant = xplustabs();
577 if (current->lineno >= editbot->lineno)
578 edit_update(current);
579
580}
581
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000582void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000583{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000584 int i = 0; /* Index into ->data for line. */
585 int i_tabs = 0; /* Screen position of ->data[i]. */
586 int last_word_end = -1; /* Location of end of last word found. */
587 int current_word_start = -1; /* Location of start of current word. */
588 int current_word_start_t = -1; /* Location of start of current word screen position. */
589 int current_word_end = -1; /* Location of end of current word */
590 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000591 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000592
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000593 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000594 int right = 0;
595 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000596
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000597 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000598
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000599 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000600 if (!isspace(inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000601 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000602
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000603 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000604 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000605
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000606 while (!isspace(inptr->data[i]) && inptr->data[i]) {
607 i++;
608 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000609 if (inptr->data[i] < 32)
610 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000611 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000612
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000613 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000614 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000615 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000616 } else {
617 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000618 current_word_end_t = i_tabs - 1;
619 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000620 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000621
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000622 if (inptr->data[i] == NANO_CONTROL_I) {
623 if (i_tabs % TABSIZE != 0);
624 i_tabs += TABSIZE - (i_tabs % TABSIZE);
625 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000626
Adam Rogoyski09f97962000-06-20 02:50:33 +0000627 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000628 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000629 }
630
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000631 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000632 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000633 * a) one word takes up the whole line with no starting spaces.
634 * - do nothing and return.
635 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000636 * - word starts new line.
637 * - keep white space on original line up to the cursor.
638 * *) cursor is after word at wrap point
639 * - either it's all white space after word, and this routine isn't called.
640 * - or we are actually in case 2 (2 words).
641 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000642 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000643 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000644 * - white space at end of original line is cleared, unless
645 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000646 * b) cursor is at the word at the wrap point.
647 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000648 * 1. pressed a space and at first character of wrap point word.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000649 * - white space on original line is kept to where cursor was.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000650 * 2. pressed non space (or space elsewhere).
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000651 * - white space at end of original line is cleared.
652 * c) cursor is past the word at the wrap point.
653 * - word at wrap point starts a new line.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000654 * - white space at end of original line is cleared
655 */
656
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000657 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000658
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000659 /* Category 1a: one word taking up the whole line with no beginning spaces. */
660 if ((last_word_end == -1) && (!isspace(inptr->data[0]))) {
661 for (i = current_word_end; i < len; i++) {
662 if (!isspace(inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000663 current_word_start = i;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000664 while (!isspace(inptr->data[i]) && (i < len)) {
665 i++;
666 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000667 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000668 current_word_end = i;
669 break;
670 }
671 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000672
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000673 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000674 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000675 return;
676 }
677 if (current_x >= last_word_end) {
678 right = (current_x - current_word_start) + 1;
679 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000680 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000681 }
682
683 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
684 strcpy(temp->data, &inptr->data[current_word_start]);
685 inptr->data = nrealloc(inptr->data, last_word_end + 2);
686 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000687 } else
688 /* Category 1b: one word on the line and word not taking up whole line
689 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000690 if (last_word_end == -1) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000691 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
692 strcpy(temp->data, &inptr->data[current_word_start]);
693
694 /* Inside word, remove it from original, and move cursor to right spot. */
695 if (current_x >= current_word_start) {
696 right = current_x - current_word_start;
697 current_x = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000698 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000699 }
700
701 inptr->data = nrealloc(inptr->data, current_x + 1);
702 inptr->data[current_x] = 0;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000703
704 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
705 mark_beginbuf = temp;
706 mark_beginx = 0;
707 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000708 }
709
710 /* Category 2: two or more words on the line. */
711 else {
712
713 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000714 if (current_x < current_word_start) {
715 temp->data =
716 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
717 strcpy(temp->data, &inptr->data[current_word_start]);
718
719 if (!isspace(input_char)) {
720 i = current_word_start - 1;
721 while (isspace(inptr->data[i])) {
722 i--;
723 assert(i >= 0);
724 }
725 } else if (current_x <= last_word_end)
726 i = last_word_end - 1;
727 else
728 i = current_x;
729
730 inptr->data = nrealloc(inptr->data, i + 2);
731 inptr->data[i + 1] = 0;
732 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000733
734
735 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000736 else if ((current_x >= current_word_start)
737 && (current_x <= (current_word_end + 1))) {
738 temp->data =
739 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000740 strcpy(temp->data, &inptr->data[current_word_start]);
741
742 down = 1;
743
744 right = current_x - current_word_start;
745 i = current_word_start - 1;
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000746 if (isspace(input_char) && (current_x == current_word_start)) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000747 current_x = current_word_start;
748
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000749 inptr->data =
750 nrealloc(inptr->data, current_word_start + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000751 inptr->data[current_word_start] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000752 } else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000753
754 while (isspace(inptr->data[i])) {
755 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000756 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000757 }
758 inptr->data = nrealloc(inptr->data, i + 2);
759 inptr->data[i + 1] = 0;
760 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000761 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000762
763
764 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000765 else {
766 temp->data =
767 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000768 strcpy(temp->data, &inptr->data[current_word_start]);
769
770 down = 1;
771 right = current_x - current_word_start;
772
773 current_x = current_word_start;
774 i = current_word_start - 1;
775
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000776 while (isspace(inptr->data[i])) {
777 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000778 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000779 inptr->data = nrealloc(inptr->data, i + 2);
780 inptr->data[i + 1] = 0;
781 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000782 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000783 }
784
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000785 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000786 if (ISSET(SAMELINEWRAP) && inptr->next) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000787 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
788 char *p =
789 nmalloc(strlen(temp->data) + strlen(inptr->next->data) + 2);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000790 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000791
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000792 strcpy(p, temp->data);
793 strcat(p, " ");
794 strcat(p, inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000795
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000796 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000797 inptr->next->data = p;
798
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000799 free(temp->data);
800 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000801
802
803 /* The next line line may need to be wrapped as well. */
804 current_y = old_y + 1;
805 current_x = strlen(inptr->next->data);
806 while (current_x >= 0) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000807 if (isspace(inptr->next->data[current_x])
808 && (current_x < fill)) break;
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000809 current_x--;
810 }
811 if (current_x >= 0)
812 check_wrap(inptr->next, ' ');
813
814 current_x = old_x;
815 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000816 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000817 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000818 else {
819 temp->prev = inptr;
820 temp->next = inptr->next;
821
822 if (inptr->next)
823 inptr->next->prev = temp;
824 inptr->next = temp;
825
826 if (!temp->next)
827 filebot = temp;
828
829 SET(SAMELINEWRAP);
830 }
831
832
833 totlines++;
834 totsize++;
835
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000836 renumber(inptr);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000837 edit_update_top(edittop);
838
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000839
840 /* Move the cursor to the new line if appropriate. */
841 if (down) {
842 do_right();
843 }
844
845 /* Move the cursor to the correct spot in the line if appropriate. */
846 while (right--) {
847 do_right();
848 }
849
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000850 edit_update_top(edittop);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000851 reset_cursor();
852 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000853}
854
855/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000856void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000857{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000858 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000859#ifdef DEBUG
860 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
861 inptr->data);
862#endif
863
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000864 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000865 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000866 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000867 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000868
869 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000870 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000871
Adam Rogoyski09f97962000-06-20 02:50:33 +0000872 while (isspace(inptr->data[i]) && inptr->data[i])
873 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000874
Adam Rogoyski09f97962000-06-20 02:50:33 +0000875 if (!inptr->data[i])
876 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000877
Adam Rogoyski09f97962000-06-20 02:50:33 +0000878 /* String must be at least 1 character long. */
879 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
880 if (isspace(inptr->data[i])) {
881 if (!char_found)
882 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000883 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000884 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000885 } else
886 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000887 }
Adam Rogoyski09f97962000-06-20 02:50:33 +0000888
889 if (char_found == 2)
890 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000891 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000892}
893
894/* Stuff we do when we abort from programs and want to clean up the
895 * screen. This doesnt do much right now.
896 */
897void do_early_abort(void)
898{
899 blank_statusbar_refresh();
900}
901
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000902void delete_buffer(filestruct * inptr)
903{
904 if (inptr != NULL) {
905 delete_buffer(inptr->next);
906 free(inptr->data);
907 free(inptr);
908 }
909}
910
911int do_backspace(void)
912{
913 filestruct *previous, *tmp;
914
915 if (current_x != 0) {
916 /* Let's get dangerous */
917 memmove(&current->data[current_x - 1], &current->data[current_x],
918 strlen(current->data) - current_x + 1);
919#ifdef DEBUG
920 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
921#endif
922 align(&current->data);
923 do_left();
924 } else {
925 if (current == fileage)
926 return 0; /* Can't delete past top of file */
927
928 previous = current->prev;
929 current_x = strlen(previous->data);
930 previous->data = nrealloc(previous->data,
931 strlen(previous->data) +
932 strlen(current->data) + 1);
933 strcat(previous->data, current->data);
934
935 tmp = current;
936 unlink_node(current);
937 delete_node(current);
938 if (current == edittop) {
939 if (previous->next)
940 current = previous->next;
941 else
942 current = previous;
943 page_up();
944 } else {
945 if (previous->next)
946 current = previous->next;
947 else
948 current = previous;
949 update_line(current, current_x);
950 }
951
952 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000953 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000954 filebot = current;
955 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +0000956
957 /* Recreate the magic line if we're deleting it AND if the
958 line we're on now is NOT blank. if it is blank we
959 can just use IT for the magic line. This is how Pico
960 appears to do it, in any case */
961 if (strcmp(current->data, "")) {
962 new_magicline();
963 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +0000964 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +0000965 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000966 }
967
968 current = previous;
969 renumber(current);
970 previous_line();
971 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000972#ifdef DEBUG
973 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
974#endif
975
976 }
977
978 totsize--;
979 set_modified();
980 UNSET(KEEP_CUTBUFFER);
981 edit_refresh();
982 return 1;
983}
984
985int do_delete(void)
986{
987 filestruct *foo;
988
989 if (current_x != strlen(current->data)) {
990 /* Let's get dangerous */
991 memmove(&current->data[current_x], &current->data[current_x + 1],
992 strlen(current->data) - current_x);
993
994 align(&current->data);
995
996 } else if (current->next != NULL) {
997 current->data = nrealloc(current->data,
998 strlen(current->data) +
999 strlen(current->next->data) + 1);
1000 strcat(current->data, current->next->data);
1001
1002 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001003 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001004 filebot = current;
1005 editbot = current;
1006 }
1007
1008 unlink_node(foo);
1009 delete_node(foo);
1010 update_line(current, current_x);
1011
Chris Allegretta28a0f892000-07-05 22:47:54 +00001012 /* Please see the comment in do_basckspace if you don't understand
1013 this test */
1014 if (current == filebot && strcmp(current->data, ""))
1015 {
1016 new_magicline();
1017 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001018 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001019 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001020 renumber(current);
1021 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001022 } else
1023 return 0;
1024
1025 totsize--;
1026 set_modified();
1027 UNSET(KEEP_CUTBUFFER);
1028 edit_refresh();
1029 return 1;
1030}
1031
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001032void wrap_reset(void)
1033{
1034 UNSET(SAMELINEWRAP);
1035}
1036
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001037/* Stuff we want to do when we exit the spell program one of its many ways */
1038void exit_spell(char *tmpfilename, char *foo)
1039{
1040 free(foo);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001041
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001042 if (remove(tmpfilename) == -1)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001043 statusbar(_("Error deleting tempfile, ack!"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001044}
1045
1046/*
1047 * This is Chris' very ugly spell function. Someone please make this
1048 * better =-)
1049 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001050int do_spell(void)
1051{
Chris Allegretta67105eb2000-07-03 03:18:32 +00001052#ifdef NANO_SMALL
1053 nano_small_msg();
1054 return 1;
1055#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001056 char *temp, *foo;
Robert Siemborski6af14312000-07-01 21:34:26 +00001057 int i, size;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001058
1059 if ((temp = tempnam(0, "nano.")) == NULL) {
1060 statusbar(_("Could not create a temporary filename: %s"),
1061 strerror(errno));
1062 return 0;
1063 }
1064 if (write_file(temp, 1) == -1)
1065 return 0;
1066
1067 if (alt_speller) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001068 size = strlen(temp) + strlen(alt_speller) + 2;
1069 foo = nmalloc(size);
1070 snprintf(foo, size, "%s %s", alt_speller, temp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001071 } else {
1072
1073 /* For now, we only try ispell because we're not capable of
1074 handling the normal spell program (yet...) */
Robert Siemborski6af14312000-07-01 21:34:26 +00001075 size = strlen(temp) + 8;
1076 foo = nmalloc(size);
1077 snprintf(foo, size, "ispell %s", temp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001078 }
1079
1080 endwin();
1081 resetty();
1082 if (alt_speller) {
1083 if ((i = system(foo)) == -1 || i == 32512) {
1084 statusbar(_("Could not invoke spell program \"%s\""),
1085 alt_speller);
1086 exit_spell(temp, foo);
1087 return 0;
1088 }
1089 } else if ((i = system(foo)) == -1 || i == 32512) { /* Why 32512? I dont know! */
1090 statusbar(_("Could not invoke \"ispell\""));
1091 exit_spell(temp, foo);
1092 return 0;
1093 }
1094 initscr();
1095
1096 free_filestruct(fileage);
1097 global_init();
1098 open_file(temp, 0, 1);
1099 edit_update(fileage);
1100 set_modified();
1101 exit_spell(temp, foo);
1102 statusbar(_("Finished checking spelling"));
1103 return 1;
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001104#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001105}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001106
1107int do_exit(void)
1108{
1109 int i;
1110
1111 if (!ISSET(MODIFIED))
1112 finish(0);
1113
1114 if (temp_opt) {
1115 i = 1;
1116 } else {
1117 i =
1118 do_yesno(0, 0,
1119 _
1120 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1121 }
1122
1123#ifdef DEBUG
1124 dump_buffer(fileage);
1125#endif
1126
1127 if (i == 1) {
1128 if (do_writeout(1) > 0)
1129 finish(0);
1130 } else if (i == 0)
1131 finish(0);
1132 else
1133 statusbar(_("Cancelled"));
1134
1135 display_main_list();
1136 return 1;
1137}
1138
1139#ifndef NANO_SMALL
1140#ifdef NCURSES_MOUSE_VERSION
1141void do_mouse(void)
1142{
1143 MEVENT mevent;
1144
1145 if (getmouse(&mevent) == ERR)
1146 return;
1147
1148 /* If mouse not in edit window, return (add help selection later). */
1149 if (!wenclose(edit, mevent.y, mevent.x))
1150 return;
1151
1152 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1153 mevent.y -= 2;
1154
1155 /* Selecting where the cursor is sets the mark.
1156 * Selecting beyond the line length with the cursor at the end of the
1157 * line sets the mark as well.
1158 */
1159 if ((mevent.y == current_y) &&
1160 ((mevent.x == current_x) || (current_x == strlen(current->data)
1161 && (mevent.x >
1162 strlen(current->data))))) {
1163 if (ISSET(VIEW_MODE)) {
1164 print_view_warning();
1165 return;
1166 }
1167 do_mark();
1168 } else if (mevent.y > current_y) {
1169 while (mevent.y > current_y) {
1170 if (current->next != NULL)
1171 current = current->next;
1172 else
1173 break;
1174 current_y++;
1175 }
1176 } else if (mevent.y < current_y) {
1177 while (mevent.y < current_y) {
1178 if (current->prev != NULL)
1179 current = current->prev;
1180 else
1181 break;
1182 current_y--;
1183 }
1184 }
1185 current_x = mevent.x;
1186 if (current_x > strlen(current->data))
1187 current_x = strlen(current->data);
1188
1189 update_cursor();
1190 edit_refresh();
1191
1192}
1193#endif
1194#endif
1195
1196/* Handler for SIGHUP */
1197RETSIGTYPE handle_hup(int signal)
1198{
1199 write_file("nano.save", 0);
1200 finish(1);
1201}
1202
1203
1204void handle_sigwinch(int s)
1205{
1206#ifndef NANO_SMALL
1207 char *tty = NULL;
1208 int fd = 0;
1209 int result = 0;
1210 int i = 0;
1211 struct winsize win;
1212
1213 tty = ttyname(0);
1214 if (!tty)
1215 return;
1216 fd = open(tty, O_RDWR);
1217 if (fd == -1)
1218 return;
1219 result = ioctl(fd, TIOCGWINSZ, &win);
1220 if (result == -1)
1221 return;
1222
1223
1224 COLS = win.ws_col;
1225 LINES = win.ws_row;
1226
1227 center_x = COLS / 2;
1228 center_y = LINES / 2;
1229 editwinrows = LINES - 5 + no_help();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001230 fill = COLS - 8;
1231
1232 free(hblank);
1233 hblank = nmalloc(COLS + 1);
1234
1235 for (i = 0; i <= COLS - 1; i++)
1236 hblank[i] = ' ';
1237 hblank[i] = 0;
1238
1239#ifdef HAVE_NCURSES_H
1240 resizeterm(LINES, COLS);
1241#ifdef HAVE_WRESIZE
1242 if (wresize(topwin, 2, COLS) == ERR)
1243 die(_("Cannot resize top win"));
1244 if (mvwin(topwin, 0, 0) == ERR)
1245 die(_("Cannot move top win"));
1246 if (wresize(edit, editwinrows, COLS) == ERR)
1247 die(_("Cannot resize edit win"));
1248 if (mvwin(edit, 2, 0) == ERR)
1249 die(_("Cannot move edit win"));
1250 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1251 die(_("Cannot resize bottom win"));
1252 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1253 die(_("Cannot move bottom win"));
1254#endif /* HAVE_WRESIZE */
1255#endif /* HAVE_NCURSES_H */
1256
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001257 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001258
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001259 if (current_y > editwinrows - 1) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001260 edit_update(editbot);
1261 }
1262 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001263
1264 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001265 refresh();
Chris Allegretta97accc62000-06-19 05:45:52 +00001266 titlebar();
1267 edit_refresh();
1268 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001269 total_refresh();
1270#endif
1271}
1272
1273int do_tab(void)
1274{
1275 do_char('\t');
1276 return 1;
1277}
1278
1279#ifndef NANO_SMALL
1280int empty_line(const char *data)
1281{
1282 while (*data) {
1283 if (!isspace(*data))
1284 return 0;
1285
1286 data++;
1287 }
1288
1289 return 1;
1290}
1291
1292int no_spaces(const char *data)
1293{
1294 while (*data) {
1295 if (isspace(*data))
1296 return 0;
1297
1298 data++;
1299 }
1300
1301 return 1;
1302}
1303
1304void justify_format(char *data)
1305{
1306 int i = 0;
1307 int len = strlen(data);
1308
1309 /* Skip first character regardless and leading whitespace. */
1310 for (i = 1; i < len; i++) {
1311 if (!isspace(data[i]))
1312 break;
1313 }
1314
1315 i++; /* (i) is now at least 2. */
1316
1317 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
1318 for (; i < len; i++) {
1319 if (isspace(data[i]) && isspace(data[i - 1])
1320 && (data[i - 2] != '.')) {
1321 memmove(data + i, data + i + 1, len - i);
1322 len--;
1323 i--;
1324 }
1325 }
1326}
1327#endif
1328
1329int do_justify(void)
1330{
1331#ifndef NANO_SMALL
1332 int slen = 0; /* length of combined lines on one line. */
1333 int initial_y;
1334 filestruct *initial = NULL;
1335
1336 if (empty_line(current->data)) {
1337 /* Justify starting at first non-empty line. */
1338 do {
1339 if (!current->next)
1340 return 1;
1341
1342 current = current->next;
1343 current_y++;
1344 }
1345 while (empty_line(current->data));
1346 } else {
1347 /* Search back for the beginning of the paragraph, where
1348 * Paragraph is 1) A line with leading whitespace
1349 * or 2) A line following an empty line.
1350 */
1351 while (current->prev != NULL) {
1352 if (isspace(current->data[0]) || !current->data[0])
1353 break;
1354
1355 current = current->prev;
1356 current_y--;
1357 }
1358
1359 /* First line with leading whitespace may be empty. */
1360 if (empty_line(current->data)) {
1361 if (current->next) {
1362 current = current->next;
1363 current_y++;
1364 } else
1365 return 1;
1366 }
1367 }
1368 initial = current;
1369 initial_y = current_y;
1370
1371 set_modified();
1372 /* Put the whole paragraph into one big line. */
1373 while (current->next && !isspace(current->next->data[0])
1374 && current->next->data[0]) {
1375 filestruct *tmpnode = current->next;
1376 int len = strlen(current->data);
1377 int len2 = strlen(current->next->data);
1378
1379 /* length of both strings plus space between strings and ending \0. */
1380 current->data = nrealloc(current->data, len + len2 + 2);
1381 current->data[len++] = ' ';
1382 current->data[len] = '\0';
1383
1384 strncat(current->data, current->next->data, len2);
1385
1386 unlink_node(tmpnode);
1387 delete_node(tmpnode);
1388
1389 }
1390
1391 justify_format(current->data);
1392
1393 slen = strlen(current->data);
Adam Rogoyski09f97962000-06-20 02:50:33 +00001394 while ((strlenpt(current->data) > (fill))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001395 && !no_spaces(current->data)) {
1396 int i = 0;
1397 int len2 = 0;
1398 filestruct *tmpline = nmalloc(sizeof(filestruct));
1399
Adam Rogoyski09f97962000-06-20 02:50:33 +00001400 /* Start at fill , unless line isn't that long (but it appears at least
1401 * fill long with tabs.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001402 */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001403 if (slen > fill)
1404 i = fill;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001405 else
1406 i = slen;
1407 for (; i > 0; i--) {
1408 if (isspace(current->data[i]) &&
1409 ((strlenpt(current->data) - strlen(current->data + i)) <=
1410 fill)) break;
1411 }
1412 if (!i)
1413 break;
1414
1415 current->data[i] = '\0';
1416
1417 len2 = strlen(current->data + i + 1);
1418 tmpline->data = nmalloc(len2 + 1);
1419
1420 /* Skip the white space in current. */
1421 memcpy(tmpline->data, current->data + i + 1, len2);
1422 tmpline->data[len2] = '\0';
1423
1424 current->data = nrealloc(current->data, i + 1);
1425
1426 tmpline->prev = current;
1427 tmpline->next = current->next;
1428 if (current->next != NULL)
1429 current->next->prev = tmpline;
1430
1431 current->next = tmpline;
1432 current = tmpline;
1433 slen -= i + 1;
1434 current_y++;
1435 }
1436
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001437
1438 if (current->next)
1439 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00001440 else
1441 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001442 current_x = 0;
1443 placewewant = 0;
1444
Adam Rogoyski09f97962000-06-20 02:50:33 +00001445 renumber(initial);
1446 totlines = filebot->lineno;
1447
1448 werase(edit);
1449
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001450 if ((current_y < 0) || (current_y >= editwinrows - 1)
1451 || (initial_y <= 0)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001452 edit_update(current);
1453 center_cursor();
1454 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001455 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001456 }
1457
Adam Rogoyski09f97962000-06-20 02:50:33 +00001458
1459 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001460 statusbar("Justify Complete");
1461 return 1;
1462#else
1463 nano_small_msg();
1464 return 1;
1465#endif
1466}
1467
1468
1469void help_init(void)
1470{
1471 int i, sofar = 0;
1472 long allocsize = 1; /* How much space we're gonna need for the help text */
1473 char buf[BUFSIZ];
1474
1475 /* Compute the space needed for the shortcut lists - we add 15 to
1476 have room for the shortcut abbrev and its possible alternate keys */
1477 for (i = 0; i < MAIN_LIST_LEN; i++)
1478 if (main_list[i].help != NULL)
1479 allocsize += strlen(main_list[i].help) + 15;
1480
1481 allocsize += strlen(help_text_init);
1482
1483 if (help_text != NULL)
1484 free(help_text);
1485
1486 /* Allocate space for the help text */
1487 help_text = nmalloc(allocsize);
1488
1489 /* Now add the text we want */
1490 strcpy(help_text, help_text_init);
1491
1492 /* Now add our shortcut info */
1493 for (i = 0; i < MAIN_LIST_LEN; i++) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001494 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001495
1496 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00001497 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001498 main_list[i].misc1 - KEY_F0);
1499 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001500 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001501
1502 if (main_list[i].altval > 0)
Robert Siemborski6af14312000-07-01 21:34:26 +00001503 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(@%c) ",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001504 main_list[i].altval - 32);
1505 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001506 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001507
1508 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00001509 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001510
1511 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00001512 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001513 }
1514
1515}
1516
1517int main(int argc, char *argv[])
1518{
1519 int optchr;
1520 int kbinput; /* Input from keyboard */
1521 long startline = 0; /* Line to try and start at */
1522 struct sigaction act; /* For our lovely signals */
1523 int keyhandled = 0; /* Have we handled the keystroke yet? */
1524 int tmpkey = 0, i;
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001525#ifdef HAVE_TABSIZE
1526 int usrtabsize = 0; /* User defined tab size */
1527#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001528 char *argv0;
1529 struct termios term;
1530
1531#ifdef HAVE_GETOPT_LONG
1532 int option_index = 0;
1533 struct option long_options[] = {
Chris Allegretta9fc8d432000-07-07 01:49:52 +00001534 {"regexp", 0, 0, 'R'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001535 {"version", 0, 0, 'V'},
1536 {"const", 0, 0, 'c'},
1537 {"suspend", 0, 0, 'z'},
1538 {"nowrap", 0, 0, 'w'},
1539 {"nohelp", 0, 0, 'x'},
1540 {"help", 0, 0, 'h'},
1541 {"autoindent", 0, 0, 'i'},
1542 {"tempfile", 0, 0, 't'},
1543 {"speller", 1, 0, 's'},
1544 {"fill", 1, 0, 'r'},
1545 {"mouse", 0, 0, 'm'},
1546 {"pico", 0, 0, 'p'},
1547 {"nofollow", 0, 0, 'l'},
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001548#ifdef HAVE_TABSIZE
1549 {"tabsize", 0, 0, 'T'},
1550#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001551 {0, 0, 0, 0}
1552 };
1553#endif
1554
1555 /* Flag inits... */
1556 SET(FOLLOW_SYMLINKS);
1557
1558#ifndef NANO_SMALL
1559 setlocale(LC_ALL, "");
1560 bindtextdomain(PACKAGE, LOCALEDIR);
1561 textdomain(PACKAGE);
1562#endif
1563
1564#ifdef HAVE_GETOPT_LONG
Chris Allegretta9fc8d432000-07-07 01:49:52 +00001565 while ((optchr = getopt_long(argc, argv, "?T:RVchilmpr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001566 long_options, &option_index)) != EOF) {
1567#else
Chris Allegretta9fc8d432000-07-07 01:49:52 +00001568 while ((optchr = getopt(argc, argv, "h?T:RVcilmpr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001569#endif
1570
1571 switch (optchr) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001572#ifdef HAVE_TABSIZE
1573 case 'T':
1574 usrtabsize = atoi(optarg);
1575 if (usrtabsize <= 0) {
1576 usage(); /* To stop bogus data for tab width */
1577 finish(1);
1578 }
1579 break;
1580#else
1581 case 'T':
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001582 usage(); /* Oops! You dont really have that option */
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001583 finish(1);
1584#endif
Chris Allegretta9fc8d432000-07-07 01:49:52 +00001585 case 'R':
1586 SET(USE_REGEXP);
1587 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001588 case 'V':
1589 version();
1590 exit(0);
1591 case 'c':
1592 SET(CONSTUPDATE);
1593 break;
1594 case 'h':
1595 case '?':
1596 usage();
1597 exit(0);
1598 case 'i':
1599 SET(AUTOINDENT);
1600 break;
1601 case 'l':
1602 UNSET(FOLLOW_SYMLINKS);
1603 break;
1604 case 'm':
1605 SET(USE_MOUSE);
1606 break;
1607 case 'p':
1608 SET(PICO_MSGS);
1609 break;
1610 case 'r':
1611 fill = atoi(optarg);
1612 if (fill <= 0) {
1613 usage(); /* To stop bogus data (like a string) */
1614 finish(1);
1615 }
1616 break;
1617 case 's':
1618 alt_speller = nmalloc(strlen(optarg) + 1);
1619 strcpy(alt_speller, optarg);
1620 break;
1621 case 't':
1622 temp_opt = 1;
1623 break;
1624 case 'v':
1625 SET(VIEW_MODE);
1626 break;
1627 case 'w':
1628 SET(NO_WRAP);
1629 break;
1630 case 'x':
1631 SET(NO_HELP);
1632 break;
1633 case 'z':
1634 SET(SUSPEND);
1635 break;
1636 default:
1637 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001638 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001639 }
1640
1641 }
1642
1643 argv0 = strrchr(argv[0], '/');
1644 if ((argv0 && strstr(argv0, "pico"))
1645 || (!argv0 && strstr(argv[0], "pico")))
1646 SET(PICO_MSGS);
1647
1648 filename = nmalloc(PATH_MAX);
1649 strcpy(filename, "");
1650
1651 /* See if there's a non-option in argv (first non-option is the
1652 filename, if +LINE is not given) */
1653 if (argc == 1 || argc <= optind)
1654 strcpy(filename, "");
1655 else {
1656 /* Look for the +line flag... */
1657 if (argv[optind][0] == '+') {
1658 startline = atoi(&argv[optind][1]);
1659 optind++;
1660 if (argc == 1 || argc <= optind)
1661 strcpy(filename, "");
1662 else
1663 strncpy(filename, argv[optind], 132);
1664 } else
1665 strncpy(filename, argv[optind], 132);
1666
1667 }
1668
1669
1670 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001671 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001672
1673 /* Adam's code to blow away intr character so ^C can show cursor pos */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001674 tcgetattr(0, &term);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001675 for (i = 0; i < NCCS; i++) {
1676 if (term.c_cc[i] == CINTR || term.c_cc[i] == CQUIT)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001677 term.c_cc[i] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001678 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001679 tcsetattr(0, TCSANOW, &term);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001680
1681 /* now ncurses init stuff... */
1682 initscr();
1683 savetty();
1684 nonl();
1685 cbreak();
1686 noecho();
1687 timeout(0);
1688
1689 /* Set up some global variables */
1690 global_init();
1691 shortcut_init();
1692 init_help_msg();
1693 help_init();
1694
1695 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001696 memset(&act, 0, sizeof(struct sigaction));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001697 act.sa_handler = SIG_IGN;
1698 sigaction(SIGINT, &act, NULL);
1699 sigaction(SIGQUIT, &act, NULL);
1700
1701 if (!ISSET(SUSPEND))
1702 sigaction(SIGTSTP, &act, NULL);
1703
1704 /* Trap SIGHUP cuz we want to write the file out. */
1705 act.sa_handler = handle_hup;
1706 sigaction(SIGHUP, &act, NULL);
1707
1708 act.sa_handler = handle_sigwinch;
1709 sigaction(SIGWINCH, &act, NULL);
1710
1711#ifdef DEBUG
1712 fprintf(stderr, _("Main: set up windows\n"));
1713#endif
1714
1715 /* Setup up the main text window */
1716 edit = newwin(editwinrows, COLS, 2, 0);
1717 keypad(edit, TRUE);
1718
1719#ifndef NANO_SMALL
1720#ifdef NCURSES_MOUSE_VERSION
1721 if (ISSET(USE_MOUSE)) {
1722 mousemask(BUTTON1_RELEASED, NULL);
1723 mouseinterval(50);
1724 }
1725#endif
1726#endif
1727
1728 /* And the other windows */
1729 topwin = newwin(2, COLS, 0, 0);
1730 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
1731 keypad(bottomwin, TRUE);
1732
1733#ifdef DEBUG
1734 fprintf(stderr, _("Main: bottom win\n"));
1735#endif
1736 /* Set up up bottom of window */
1737 display_main_list();
1738
1739#ifdef DEBUG
1740 fprintf(stderr, _("Main: open file\n"));
1741#endif
1742
1743 titlebar();
1744 if (argc == 1)
1745 new_file();
1746 else
1747 open_file(filename, 0, 0);
1748
1749 if (startline > 0)
1750 do_gotoline(startline);
1751 else
1752 edit_update(fileage);
1753
1754 edit_refresh();
1755 reset_cursor();
1756
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001757#ifdef HAVE_TABSIZE
1758 if (usrtabsize > 0)
1759 TABSIZE = usrtabsize;
1760#endif
1761
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001762 while (1) {
1763 kbinput = wgetch(edit);
1764 if (kbinput == 27) { /* Grab Alt-key stuff first */
1765 switch (kbinput = wgetch(edit)) {
1766 case 91:
1767
1768 switch (kbinput = wgetch(edit)) {
1769 case 'A':
1770 kbinput = KEY_UP;
1771 break;
1772 case 'B':
1773 kbinput = KEY_DOWN;
1774 break;
1775 case 'C':
1776 kbinput = KEY_RIGHT;
1777 break;
1778 case 'D':
1779 kbinput = KEY_LEFT;
1780 break;
1781 case 'H':
1782 kbinput = KEY_HOME;
1783 break;
1784 case 'F':
1785 kbinput = KEY_END;
1786 break;
1787 case 49: /* X window F-keys */
1788 tmpkey = wgetch(edit);
1789 kbinput = KEY_F(tmpkey) - 48;
1790 wgetch(edit); /* Junk character */
1791 break;
1792 case 53: /* page up */
1793 kbinput = KEY_PPAGE;
1794 if ((kbinput = wgetch(edit)) == 126)
1795 kbinput = KEY_PPAGE; /* Ignore extra tilde */
1796 else { /* I guess this could happen ;-) */
1797 ungetch(kbinput);
1798 continue;
1799 }
1800 break;
1801 case 54: /* page down */
1802 kbinput = KEY_NPAGE;
1803 if ((kbinput = wgetch(edit)) == 126)
1804 kbinput = KEY_NPAGE; /* Same thing here */
1805 else {
1806 ungetch(kbinput);
1807 continue;
1808 }
1809 break;
1810
1811 default:
1812#ifdef DEBUG
1813 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
1814 kbinput, kbinput);
1815#endif
1816 break;
1817 }
1818 break;
1819 default:
1820
1821 /* Check for the altkey defs.... */
1822 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
1823 if (kbinput == main_list[i].altval ||
1824 kbinput == main_list[i].altval - 32) {
1825 kbinput = main_list[i].val;
1826 break;
1827 }
1828#ifdef DEBUG
1829 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
1830 kbinput);
1831#endif
1832 break;
1833 }
1834 }
1835 /* Look through the main shortcut list to see if we've hit a
1836 shortcut key */
1837 for (i = 0; i < MAIN_LIST_LEN; i++) {
1838 if (kbinput == main_list[i].val ||
1839 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
1840 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
1841 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
1842 print_view_warning();
1843 else
1844 main_list[i].func();
1845 keyhandled = 1;
1846 }
1847 }
1848 /* Last gasp, stuff that's not in the main lists */
1849 if (!keyhandled)
1850 switch (kbinput) {
1851#ifndef NANO_SMALL
1852#ifdef NCURSES_MOUSE_VERSION
1853 case KEY_MOUSE:
1854 do_mouse();
1855 break;
1856#endif
1857#endif
1858 case 0: /* Erg */
1859 do_next_word();
1860 break;
1861 case 331: /* Stuff that we don't want to do squat */
1862 case -1:
1863 case 410: /* Must ignore this, it gets sent when we resize */
1864 break;
1865 default:
1866#ifdef DEBUG
1867 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
1868#endif
1869 /* We no longer stop unhandled sequences so that people with
1870 odd character sets can type... */
1871
1872 if (ISSET(VIEW_MODE)) {
1873 print_view_warning();
1874 break;
1875 }
1876 do_char(kbinput);
1877 }
1878 if (ISSET(CONSTUPDATE))
1879 do_cursorpos();
1880
1881 reset_cursor();
1882 wrefresh(edit);
1883 keyhandled = 0;
1884 }
1885
1886 getchar();
1887 finish(0);
1888
1889}