blob: c02ba86ec1f78848747c8b6072ef9bb5588142a6 [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 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000063int fill = 0; /* Fill - where to wrap lines, basically */
64static char *alt_speller; /* Alternative spell command */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000065struct termios oldterm; /* The user's original term settings */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000066static char *help_text_init = "";
67 /* Initial message, not including shortcuts */
68
69/* What we do when we're all set to exit */
70RETSIGTYPE finish(int sigage)
71{
72 if (!ISSET(NO_HELP)) {
73 mvwaddstr(bottomwin, 1, 0, hblank);
74 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000075 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000076 mvwaddstr(bottomwin, 0, 0, hblank);
77
78 wrefresh(bottomwin);
79 endwin();
80
81 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +000082 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000083
84 exit(sigage);
85}
86
87/* Die (gracefully?) */
88void die(char *msg, ...)
89{
90 va_list ap;
91
92 va_start(ap, msg);
93 vfprintf(stderr, msg, ap);
94 va_end(ap);
95
96 /* if we can't save we have REAL bad problems,
Robert Siemborskifcf32bf2000-07-17 03:04:54 +000097 * but we might as well TRY. */
98 if(filename[0] == '\0') {
99 write_file("nano.save", 0);
100 } else {
101 char buf[BUFSIZ];
102 strncpy(buf,filename,BUFSIZ);
103 strncat(buf,".save",BUFSIZ - strlen(buf));
104 write_file(buf, 0);
105 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000106 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000107 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000108
109 clear();
110 refresh();
111 resetty();
112 endwin();
113
114 fprintf(stderr, msg);
115 fprintf(stderr, _("\nBuffer written to 'nano.save'\n"));
116
117 exit(1); /* We have a problem: exit w/ errorlevel(1) */
118}
119
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000120void print_view_warning(void)
121{
122 statusbar(_("Key illegal in VIEW mode"));
123}
124
125/* Initialize global variables - no better way for now */
126void global_init(void)
127{
128 int i;
129
130 center_x = COLS / 2;
131 center_y = LINES / 2;
132 current_x = 0;
133 current_y = 0;
134 editwinrows = LINES - 5 + no_help();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000135 fileage = NULL;
136 cutbuffer = NULL;
137 current = NULL;
138 edittop = NULL;
139 editbot = NULL;
140 totlines = 0;
141 placewewant = 0;
142 if (!fill)
143 fill = COLS - 8;
144 hblank = nmalloc(COLS + 1);
145
146 /* Thanks BG for this bit... */
147 for (i = 0; i <= COLS - 1; i++)
148 hblank[i] = ' ';
149 hblank[i] = 0;
150 last_search = nmalloc(132);
151 last_replace = nmalloc(132);
152 answer = nmalloc(132);
153
154}
155
156void init_help_msg(void)
157{
158
159#ifndef NANO_SMALL
160
161 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000162 _(" nano help text\n\n "
163 "The nano editor is designed to emulate the functionality and "
164 "ease-of-use of the UW Pico text editor. There are four main "
165 "sections of the editor: The top line shows the program "
166 "version, the current filename being edited, and whether "
167 "or not the file has been modified. Next is the main editor "
168 "window showing the file being edited. The status line is "
169 "the third line from the bottom and shows important messages. "
170 "The bottom two lines show the most commonly used shortcuts "
171 "in the editor.\n\n "
172 "The notation for shortcuts is as follows: Control-key "
173 "sequences are notated with a caret (^) symbol. Alt-key "
174 "sequences are notated with an at (@) symbol. The following "
175 "keystrokes are available in the main editor window. "
176 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000177#endif
178
179}
180
181/* Make a copy of a node to a pointer (space will be malloc()ed) */
182filestruct *copy_node(filestruct * src)
183{
184 filestruct *dst;
185
186 dst = nmalloc(sizeof(filestruct));
187 dst->data = nmalloc(strlen(src->data) + 1);
188
189 dst->next = src->next;
190 dst->prev = src->prev;
191
192 strcpy(dst->data, src->data);
193 dst->lineno = src->lineno;
194
195 return dst;
196}
197
198/* Unlink a node from the rest of the struct */
199void unlink_node(filestruct * fileptr)
200{
201 if (fileptr->prev != NULL)
202 fileptr->prev->next = fileptr->next;
203
204 if (fileptr->next != NULL)
205 fileptr->next->prev = fileptr->prev;
206}
207
208void delete_node(filestruct * fileptr)
209{
210 if (fileptr->data != NULL)
211 free(fileptr->data);
212 free(fileptr);
213}
214
215/* Okay, now let's duplicate a whole struct! */
216filestruct *copy_filestruct(filestruct * src)
217{
218 filestruct *dst, *tmp, *head, *prev;
219
220 head = copy_node(src);
221 dst = head; /* Else we barf on copying just one line */
222 head->prev = NULL;
223 tmp = src->next;
224 prev = head;
225
226 while (tmp != NULL) {
227 dst = copy_node(tmp);
228 dst->prev = prev;
229 prev->next = dst;
230
231 prev = dst;
232 tmp = tmp->next;
233 }
234
235 dst->next = NULL;
236 return head;
237}
238
239/* Free() a single node */
240int free_node(filestruct * src)
241{
242 if (src == NULL)
243 return 0;
244
245 if (src->next != NULL)
246 free(src->data);
247 free(src);
248 return 1;
249}
250
251int free_filestruct(filestruct * src)
252{
253 filestruct *fileptr = src;
254
255 if (src == NULL)
256 return 0;
257
258 while (fileptr->next != NULL) {
259 fileptr = fileptr->next;
260 free_node(fileptr->prev);
261
262#ifdef DEBUG
263 fprintf(stderr, _("free_node(): free'd a node, YAY!\n"));
264#endif
265 }
266 free_node(fileptr);
267#ifdef DEBUG
268 fprintf(stderr, _("free_node(): free'd last node.\n"));
269#endif
270
271 return 1;
272}
273
274int renumber_all(void)
275{
276 filestruct *temp;
277 long i = 1;
278
279 for (temp = fileage; temp != NULL; temp = temp->next) {
280 temp->lineno = i++;
281 }
282
283 return 0;
284}
285
286int renumber(filestruct * fileptr)
287{
288 filestruct *temp;
289
290 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
291 renumber_all();
292 return 0;
293 }
294 for (temp = fileptr; temp != NULL; temp = temp->next) {
295 temp->lineno = temp->prev->lineno + 1;
296 }
297
298 return 0;
299}
300
301/* Fix the memory allocation for a string */
302void align(char **strp)
303{
304 /* There was a serious bug here: the new address was never
305 stored anywhere... */
306
307 *strp = nrealloc(*strp, strlen(*strp) + 1);
308}
309
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000310void usage(void)
311{
312#ifdef HAVE_GETOPT_LONG
313 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
314 printf(_("Option Long option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000315#ifdef HAVE_TABSIZE
316 printf(_
317 (" -T --tabsize=[num] Set width of a tab to num\n"));
318#endif
Chris Allegretta47805612000-07-07 02:35:34 +0000319#ifdef _POSIX_VERSION
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000320 printf(_
321 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000322#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000323 printf
324 (_
325 (" -V --version Print version information and exit\n"));
326 printf(_
327 (" -c --const Constantly show cursor position\n"));
328 printf(_
329 (" -h --help Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000330#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000331 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000332 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000333#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000334 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000335 (" -i --autoindent Automatically indent new lines\n"));
336 printf(_
337 (" -l --nofollow Don't follow symbolic links, overwrite.\n"));
338#ifndef NANO_SMALL
339#ifdef NCURSES_MOUSE_VERSION
340 printf(_(" -m --mouse Enable mouse\n"));
341#endif
342#endif
343 printf
344 (_
345 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
346 printf(_
347 (" -p --pico Make bottom 2 lines more Pico-like\n"));
348 printf(_
349 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
350 printf(_
351 (" -t --tempfile Auto save on exit, don't prompt\n"));
352 printf(_
353 (" -v --view View (read only) mode\n"));
354 printf(_
355 (" -w --nowrap Don't wrap long lines\n"));
356 printf(_
357 (" -x --nohelp Don't show help window\n"));
358 printf(_
359 (" -z --suspend Enable suspend\n"));
360 printf(_
361 (" +LINE Start at line number LINE\n"));
362#else
363 printf(_("Usage: nano [option] +LINE <file>\n\n"));
364 printf(_("Option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000365#ifdef HAVE_TABSIZE
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000366 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000367#endif
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000368 printf(_(" -R Use regular expressions for search\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000369 printf(_(" -V Print version information and exit\n"));
370 printf(_(" -c Constantly show cursor position\n"));
371 printf(_(" -h Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000372#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +0000373 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000374#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000375 printf(_(" -i Automatically indent new lines\n"));
376 printf(_
377 (" -l Don't follow symbolic links, overwrite.\n"));
378#ifndef NANO_SMALL
379#ifdef NCURSES_MOUSE_VERSION
380 printf(_(" -m Enable mouse\n"));
381#endif
382#endif
383 printf(_
384 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
385 printf(_(" -s [prog] Enable alternate speller\n"));
386 printf(_(" -p Make bottom 2 lines more Pico-like\n"));
387 printf(_(" -t Auto save on exit, don't prompt\n"));
388 printf(_(" -v View (read only) mode\n"));
389 printf(_(" -w Don't wrap long lines\n"));
390 printf(_(" -x Don't show help window\n"));
391 printf(_(" -z Enable suspend\n"));
392 printf(_(" +LINE Start at line number LINE\n"));
393#endif
394 exit(0);
395}
396
397void version(void)
398{
399 printf(_(" nano version %s by Chris Allegretta (compiled %s, %s)\n"),
400 VERSION, __TIME__, __DATE__);
401 printf(_(" Email: nano@asty.org Web: http://www.asty.org/nano\n"));
402}
403
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000404filestruct *make_new_node(filestruct * prevnode)
405{
406 filestruct *newnode;
407
408 newnode = nmalloc(sizeof(filestruct));
409 newnode->data = NULL;
410
411 newnode->prev = prevnode;
412 newnode->next = NULL;
413
414 if (prevnode != NULL)
415 newnode->lineno = prevnode->lineno + 1;
416
417 return newnode;
418}
419
420int do_mark()
421{
422#ifdef NANO_SMALL
423 nano_small_msg();
424#else
425 if (!ISSET(MARK_ISSET)) {
426 statusbar(_("Mark Set"));
427 SET(MARK_ISSET);
428 mark_beginbuf = current;
429 mark_beginx = current_x;
430 } else {
431 statusbar(_("Mark UNset"));
432 UNSET(MARK_ISSET);
433 mark_beginbuf = NULL;
434 mark_beginx = 0;
435
436 edit_refresh();
437 }
438#endif
439 return 1;
440}
441
442int no_help(void)
443{
444 if ISSET
445 (NO_HELP)
446 return 2;
447 else
448 return 0;
449}
450
451void nano_small_msg(void)
452{
453 statusbar("Sorry, this function not available with nano-tiny option");
454}
455
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000456/* The user typed a printable character; add it to the edit buffer */
457void do_char(char ch)
458{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000459 /* magic-line: when a character is inserted on the current magic line,
460 * it means we need a new one! */
461 if(filebot == current && current->data[0] == '\0') {
462 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000463 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000464 }
465
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000466 /* More dangerousness fun =) */
467 current->data = nrealloc(current->data, strlen(current->data) + 2);
468 memmove(&current->data[current_x + 1],
469 &current->data[current_x],
470 strlen(current->data) - current_x + 1);
471 current->data[current_x] = ch;
472 do_right();
473
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000474 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000475 check_wrap(current, ch);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000476 set_modified();
477 check_statblank();
478 UNSET(KEEP_CUTBUFFER);
479 totsize++;
480
481}
482
483/* Someone hits return *gasp!* */
484int do_enter(filestruct * inptr)
485{
486 filestruct *new;
487 char *tmp, *spc;
488 int extra = 0;
489
490 new = make_new_node(inptr);
491 tmp = &current->data[current_x];
492 current_x = 0;
493
494 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
495 if (ISSET(AUTOINDENT)) {
496 spc = current->data;
497 if (spc) {
498 while ((*spc == ' ') || (*spc == '\t')) {
499 extra++;
500 spc++;
501 current_x++;
502 }
503 new->data = nmalloc(strlen(tmp) + extra + 1);
504 strncpy(new->data, current->data, extra);
505 strcpy(&new->data[extra], tmp);
506 }
507 } else {
508 new->data = nmalloc(strlen(tmp) + 1);
509 strcpy(new->data, tmp);
510 }
511 *tmp = 0;
512
513 new->next = inptr->next;
514 new->prev = inptr;
515 inptr->next = new;
516 if (new->next != NULL)
517 new->next->prev = new;
518 else {
519 filebot = new;
520 editbot = new;
521 }
522
523 totsize++;
524 renumber(current);
525 current = new;
526 align(&current->data);
527
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000528 /* The logic here is as follows:
529 * -> If we are at the bottom of the buffer, we want to recenter
530 * (read: rebuild) the screen and forcably move the cursor.
531 * -> otherwise, we want simply to redraw the screen and update
532 * where we think the cursor is.
533 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000534 if (current_y == editwinrows - 1) {
535 edit_update(current);
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000536 reset_cursor();
537 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000538 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000539 edit_refresh();
540 update_cursor();
541 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000542
543 totlines++;
544 set_modified();
545
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000546 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000547 return 1;
548}
549
550int do_enter_void(void)
551{
552 return do_enter(current);
553}
554
555void do_next_word(void)
556{
557 filestruct *fileptr;
558 int i;
559
560 if (current == NULL)
561 return;
562
563 i = current_x;
564 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
565 if (fileptr == current) {
566 while (isalnum((int) fileptr->data[i])
567 && fileptr->data[i] != 0)
568 i++;
569
570 if (fileptr->data[i] == 0) {
571 i = 0;
572 continue;
573 }
574 }
575 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
576 i++;
577
578 if (fileptr->data[i] != 0)
579 break;
580
581 i = 0;
582 }
583 if (fileptr == NULL)
584 current = filebot;
585 else
586 current = fileptr;
587
588 current_x = i;
589 placewewant = xplustabs();
590 if (current->lineno >= editbot->lineno)
591 edit_update(current);
592
593}
594
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000595void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000596{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000597 int i = 0; /* Index into ->data for line. */
598 int i_tabs = 0; /* Screen position of ->data[i]. */
599 int last_word_end = -1; /* Location of end of last word found. */
600 int current_word_start = -1; /* Location of start of current word. */
601 int current_word_start_t = -1; /* Location of start of current word screen position. */
602 int current_word_end = -1; /* Location of end of current word */
603 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000604 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000605
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000606 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000607 int right = 0;
608 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000609
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000610 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000611
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000612 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000613 if (!isspace(inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000614 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000615
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000616 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000617 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000618
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000619 while (!isspace(inptr->data[i]) && inptr->data[i]) {
620 i++;
621 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000622 if (inptr->data[i] < 32)
623 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000624 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000625
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000626 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000627 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000628 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000629 } else {
630 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000631 current_word_end_t = i_tabs - 1;
632 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000633 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000634
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000635 if (inptr->data[i] == NANO_CONTROL_I) {
636 if (i_tabs % TABSIZE != 0);
637 i_tabs += TABSIZE - (i_tabs % TABSIZE);
638 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000639
Adam Rogoyski09f97962000-06-20 02:50:33 +0000640 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000641 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000642 }
643
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000644 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000645 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000646 * a) one word takes up the whole line with no starting spaces.
647 * - do nothing and return.
648 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000649 * - word starts new line.
650 * - keep white space on original line up to the cursor.
651 * *) cursor is after word at wrap point
652 * - either it's all white space after word, and this routine isn't called.
653 * - or we are actually in case 2 (2 words).
654 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000655 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000656 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000657 * - white space at end of original line is cleared, unless
658 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000659 * b) cursor is at the word at the wrap point.
660 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000661 * 1. pressed a space and at first character of wrap point word.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000662 * - white space on original line is kept to where cursor was.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000663 * 2. pressed non space (or space elsewhere).
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000664 * - white space at end of original line is cleared.
665 * c) cursor is past the word at the wrap point.
666 * - word at wrap point starts a new line.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000667 * - white space at end of original line is cleared
668 */
669
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000670 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000671
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000672 /* Category 1a: one word taking up the whole line with no beginning spaces. */
673 if ((last_word_end == -1) && (!isspace(inptr->data[0]))) {
674 for (i = current_word_end; i < len; i++) {
675 if (!isspace(inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000676 current_word_start = i;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000677 while (!isspace(inptr->data[i]) && (i < len)) {
678 i++;
679 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000680 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000681 current_word_end = i;
682 break;
683 }
684 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000685
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000686 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000687 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000688 return;
689 }
690 if (current_x >= last_word_end) {
691 right = (current_x - current_word_start) + 1;
692 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000693 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000694 }
695
696 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
697 strcpy(temp->data, &inptr->data[current_word_start]);
698 inptr->data = nrealloc(inptr->data, last_word_end + 2);
699 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000700 } else
701 /* Category 1b: one word on the line and word not taking up whole line
702 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000703 if (last_word_end == -1) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000704 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
705 strcpy(temp->data, &inptr->data[current_word_start]);
706
707 /* Inside word, remove it from original, and move cursor to right spot. */
708 if (current_x >= current_word_start) {
709 right = current_x - current_word_start;
710 current_x = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000711 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000712 }
713
714 inptr->data = nrealloc(inptr->data, current_x + 1);
715 inptr->data[current_x] = 0;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000716
717 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
718 mark_beginbuf = temp;
719 mark_beginx = 0;
720 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000721 }
722
723 /* Category 2: two or more words on the line. */
724 else {
725
726 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000727 if (current_x < current_word_start) {
728 temp->data =
729 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
730 strcpy(temp->data, &inptr->data[current_word_start]);
731
732 if (!isspace(input_char)) {
733 i = current_word_start - 1;
734 while (isspace(inptr->data[i])) {
735 i--;
736 assert(i >= 0);
737 }
738 } else if (current_x <= last_word_end)
739 i = last_word_end - 1;
740 else
741 i = current_x;
742
743 inptr->data = nrealloc(inptr->data, i + 2);
744 inptr->data[i + 1] = 0;
745 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000746
747
748 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000749 else if ((current_x >= current_word_start)
750 && (current_x <= (current_word_end + 1))) {
751 temp->data =
752 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000753 strcpy(temp->data, &inptr->data[current_word_start]);
754
755 down = 1;
756
757 right = current_x - current_word_start;
758 i = current_word_start - 1;
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000759 if (isspace(input_char) && (current_x == current_word_start)) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000760 current_x = current_word_start;
761
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000762 inptr->data =
763 nrealloc(inptr->data, current_word_start + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000764 inptr->data[current_word_start] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000765 } else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000766
767 while (isspace(inptr->data[i])) {
768 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000769 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000770 }
771 inptr->data = nrealloc(inptr->data, i + 2);
772 inptr->data[i + 1] = 0;
773 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000774 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000775
776
777 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000778 else {
779 temp->data =
780 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000781 strcpy(temp->data, &inptr->data[current_word_start]);
782
783 down = 1;
784 right = current_x - current_word_start;
785
786 current_x = current_word_start;
787 i = current_word_start - 1;
788
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000789 while (isspace(inptr->data[i])) {
790 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000791 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000792 inptr->data = nrealloc(inptr->data, i + 2);
793 inptr->data[i + 1] = 0;
794 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000795 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000796 }
797
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000798 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000799 if (ISSET(SAMELINEWRAP) && inptr->next) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000800 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
801 char *p =
802 nmalloc(strlen(temp->data) + strlen(inptr->next->data) + 2);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000803 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000804
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000805 strcpy(p, temp->data);
806 strcat(p, " ");
807 strcat(p, inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000808
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000809 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000810 inptr->next->data = p;
811
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000812 free(temp->data);
813 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000814
815
816 /* The next line line may need to be wrapped as well. */
817 current_y = old_y + 1;
818 current_x = strlen(inptr->next->data);
819 while (current_x >= 0) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000820 if (isspace(inptr->next->data[current_x])
821 && (current_x < fill)) break;
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000822 current_x--;
823 }
824 if (current_x >= 0)
825 check_wrap(inptr->next, ' ');
826
827 current_x = old_x;
828 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000829 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000830 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000831 else {
832 temp->prev = inptr;
833 temp->next = inptr->next;
834
835 if (inptr->next)
836 inptr->next->prev = temp;
837 inptr->next = temp;
838
839 if (!temp->next)
840 filebot = temp;
841
842 SET(SAMELINEWRAP);
843 }
844
845
846 totlines++;
847 totsize++;
848
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000849 renumber(inptr);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000850 edit_update_top(edittop);
851
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000852
853 /* Move the cursor to the new line if appropriate. */
854 if (down) {
855 do_right();
856 }
857
858 /* Move the cursor to the correct spot in the line if appropriate. */
859 while (right--) {
860 do_right();
861 }
862
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000863 edit_update_top(edittop);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000864 reset_cursor();
865 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000866}
867
868/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000869void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000870{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000871 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000872#ifdef DEBUG
873 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
874 inptr->data);
875#endif
876
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000877 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000878 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000879 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000880 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000881
882 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000883 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000884
Adam Rogoyski09f97962000-06-20 02:50:33 +0000885 while (isspace(inptr->data[i]) && inptr->data[i])
886 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000887
Adam Rogoyski09f97962000-06-20 02:50:33 +0000888 if (!inptr->data[i])
889 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000890
Adam Rogoyski09f97962000-06-20 02:50:33 +0000891 /* String must be at least 1 character long. */
892 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
893 if (isspace(inptr->data[i])) {
894 if (!char_found)
895 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000896 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000897 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000898 } else
899 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000900 }
Adam Rogoyski09f97962000-06-20 02:50:33 +0000901
902 if (char_found == 2)
903 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000904 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000905}
906
907/* Stuff we do when we abort from programs and want to clean up the
908 * screen. This doesnt do much right now.
909 */
910void do_early_abort(void)
911{
912 blank_statusbar_refresh();
913}
914
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000915void delete_buffer(filestruct * inptr)
916{
917 if (inptr != NULL) {
918 delete_buffer(inptr->next);
919 free(inptr->data);
920 free(inptr);
921 }
922}
923
924int do_backspace(void)
925{
926 filestruct *previous, *tmp;
927
928 if (current_x != 0) {
929 /* Let's get dangerous */
930 memmove(&current->data[current_x - 1], &current->data[current_x],
931 strlen(current->data) - current_x + 1);
932#ifdef DEBUG
933 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
934#endif
935 align(&current->data);
936 do_left();
937 } else {
938 if (current == fileage)
939 return 0; /* Can't delete past top of file */
940
941 previous = current->prev;
942 current_x = strlen(previous->data);
943 previous->data = nrealloc(previous->data,
944 strlen(previous->data) +
945 strlen(current->data) + 1);
946 strcat(previous->data, current->data);
947
948 tmp = current;
949 unlink_node(current);
950 delete_node(current);
951 if (current == edittop) {
952 if (previous->next)
953 current = previous->next;
954 else
955 current = previous;
956 page_up();
957 } else {
958 if (previous->next)
959 current = previous->next;
960 else
961 current = previous;
962 update_line(current, current_x);
963 }
964
965 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000966 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000967 filebot = current;
968 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +0000969
970 /* Recreate the magic line if we're deleting it AND if the
971 line we're on now is NOT blank. if it is blank we
972 can just use IT for the magic line. This is how Pico
973 appears to do it, in any case */
974 if (strcmp(current->data, "")) {
975 new_magicline();
976 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +0000977 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +0000978 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000979 }
980
981 current = previous;
982 renumber(current);
983 previous_line();
984 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000985#ifdef DEBUG
986 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
987#endif
988
989 }
990
991 totsize--;
992 set_modified();
993 UNSET(KEEP_CUTBUFFER);
994 edit_refresh();
995 return 1;
996}
997
998int do_delete(void)
999{
1000 filestruct *foo;
1001
1002 if (current_x != strlen(current->data)) {
1003 /* Let's get dangerous */
1004 memmove(&current->data[current_x], &current->data[current_x + 1],
1005 strlen(current->data) - current_x);
1006
1007 align(&current->data);
1008
1009 } else if (current->next != NULL) {
1010 current->data = nrealloc(current->data,
1011 strlen(current->data) +
1012 strlen(current->next->data) + 1);
1013 strcat(current->data, current->next->data);
1014
1015 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001016 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001017 filebot = current;
1018 editbot = current;
1019 }
1020
1021 unlink_node(foo);
1022 delete_node(foo);
1023 update_line(current, current_x);
1024
Chris Allegretta28a0f892000-07-05 22:47:54 +00001025 /* Please see the comment in do_basckspace if you don't understand
1026 this test */
1027 if (current == filebot && strcmp(current->data, ""))
1028 {
1029 new_magicline();
1030 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001031 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001032 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001033 renumber(current);
1034 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001035 } else
1036 return 0;
1037
1038 totsize--;
1039 set_modified();
1040 UNSET(KEEP_CUTBUFFER);
1041 edit_refresh();
1042 return 1;
1043}
1044
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001045void wrap_reset(void)
1046{
1047 UNSET(SAMELINEWRAP);
1048}
1049
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001050/* Stuff we want to do when we exit the spell program one of its many ways */
1051void exit_spell(char *tmpfilename, char *foo)
1052{
1053 free(foo);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001054
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001055 if (remove(tmpfilename) == -1)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001056 statusbar(_("Error deleting tempfile, ack!"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001057}
1058
1059/*
1060 * This is Chris' very ugly spell function. Someone please make this
1061 * better =-)
1062 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001063int do_spell(void)
1064{
Chris Allegretta67105eb2000-07-03 03:18:32 +00001065#ifdef NANO_SMALL
1066 nano_small_msg();
1067 return 1;
1068#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001069 char *temp, *foo;
Robert Siemborski6af14312000-07-01 21:34:26 +00001070 int i, size;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001071
1072 if ((temp = tempnam(0, "nano.")) == NULL) {
1073 statusbar(_("Could not create a temporary filename: %s"),
1074 strerror(errno));
1075 return 0;
1076 }
1077 if (write_file(temp, 1) == -1)
1078 return 0;
1079
1080 if (alt_speller) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001081 size = strlen(temp) + strlen(alt_speller) + 2;
1082 foo = nmalloc(size);
1083 snprintf(foo, size, "%s %s", alt_speller, temp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001084 } else {
1085
1086 /* For now, we only try ispell because we're not capable of
1087 handling the normal spell program (yet...) */
Robert Siemborski6af14312000-07-01 21:34:26 +00001088 size = strlen(temp) + 8;
1089 foo = nmalloc(size);
1090 snprintf(foo, size, "ispell %s", temp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001091 }
1092
1093 endwin();
1094 resetty();
1095 if (alt_speller) {
1096 if ((i = system(foo)) == -1 || i == 32512) {
1097 statusbar(_("Could not invoke spell program \"%s\""),
1098 alt_speller);
1099 exit_spell(temp, foo);
1100 return 0;
1101 }
1102 } else if ((i = system(foo)) == -1 || i == 32512) { /* Why 32512? I dont know! */
1103 statusbar(_("Could not invoke \"ispell\""));
1104 exit_spell(temp, foo);
1105 return 0;
1106 }
1107 initscr();
1108
1109 free_filestruct(fileage);
1110 global_init();
1111 open_file(temp, 0, 1);
1112 edit_update(fileage);
1113 set_modified();
1114 exit_spell(temp, foo);
1115 statusbar(_("Finished checking spelling"));
1116 return 1;
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001117#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001118}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001119
1120int do_exit(void)
1121{
1122 int i;
1123
1124 if (!ISSET(MODIFIED))
1125 finish(0);
1126
Chris Allegretta30885552000-07-14 01:20:12 +00001127 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001128 i = 1;
1129 } else {
1130 i =
1131 do_yesno(0, 0,
1132 _
1133 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1134 }
1135
1136#ifdef DEBUG
1137 dump_buffer(fileage);
1138#endif
1139
1140 if (i == 1) {
1141 if (do_writeout(1) > 0)
1142 finish(0);
1143 } else if (i == 0)
1144 finish(0);
1145 else
1146 statusbar(_("Cancelled"));
1147
1148 display_main_list();
1149 return 1;
1150}
1151
1152#ifndef NANO_SMALL
1153#ifdef NCURSES_MOUSE_VERSION
1154void do_mouse(void)
1155{
1156 MEVENT mevent;
1157
1158 if (getmouse(&mevent) == ERR)
1159 return;
1160
1161 /* If mouse not in edit window, return (add help selection later). */
1162 if (!wenclose(edit, mevent.y, mevent.x))
1163 return;
1164
1165 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1166 mevent.y -= 2;
1167
1168 /* Selecting where the cursor is sets the mark.
1169 * Selecting beyond the line length with the cursor at the end of the
1170 * line sets the mark as well.
1171 */
1172 if ((mevent.y == current_y) &&
1173 ((mevent.x == current_x) || (current_x == strlen(current->data)
1174 && (mevent.x >
1175 strlen(current->data))))) {
1176 if (ISSET(VIEW_MODE)) {
1177 print_view_warning();
1178 return;
1179 }
1180 do_mark();
1181 } else if (mevent.y > current_y) {
1182 while (mevent.y > current_y) {
1183 if (current->next != NULL)
1184 current = current->next;
1185 else
1186 break;
1187 current_y++;
1188 }
1189 } else if (mevent.y < current_y) {
1190 while (mevent.y < current_y) {
1191 if (current->prev != NULL)
1192 current = current->prev;
1193 else
1194 break;
1195 current_y--;
1196 }
1197 }
1198 current_x = mevent.x;
1199 if (current_x > strlen(current->data))
1200 current_x = strlen(current->data);
1201
1202 update_cursor();
1203 edit_refresh();
1204
1205}
1206#endif
1207#endif
1208
1209/* Handler for SIGHUP */
1210RETSIGTYPE handle_hup(int signal)
1211{
1212 write_file("nano.save", 0);
1213 finish(1);
1214}
1215
1216
1217void handle_sigwinch(int s)
1218{
1219#ifndef NANO_SMALL
1220 char *tty = NULL;
1221 int fd = 0;
1222 int result = 0;
1223 int i = 0;
1224 struct winsize win;
1225
1226 tty = ttyname(0);
1227 if (!tty)
1228 return;
1229 fd = open(tty, O_RDWR);
1230 if (fd == -1)
1231 return;
1232 result = ioctl(fd, TIOCGWINSZ, &win);
1233 if (result == -1)
1234 return;
1235
1236
1237 COLS = win.ws_col;
1238 LINES = win.ws_row;
1239
1240 center_x = COLS / 2;
1241 center_y = LINES / 2;
1242 editwinrows = LINES - 5 + no_help();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001243 fill = COLS - 8;
1244
1245 free(hblank);
1246 hblank = nmalloc(COLS + 1);
1247
1248 for (i = 0; i <= COLS - 1; i++)
1249 hblank[i] = ' ';
1250 hblank[i] = 0;
1251
1252#ifdef HAVE_NCURSES_H
1253 resizeterm(LINES, COLS);
1254#ifdef HAVE_WRESIZE
1255 if (wresize(topwin, 2, COLS) == ERR)
1256 die(_("Cannot resize top win"));
1257 if (mvwin(topwin, 0, 0) == ERR)
1258 die(_("Cannot move top win"));
1259 if (wresize(edit, editwinrows, COLS) == ERR)
1260 die(_("Cannot resize edit win"));
1261 if (mvwin(edit, 2, 0) == ERR)
1262 die(_("Cannot move edit win"));
1263 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1264 die(_("Cannot resize bottom win"));
1265 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1266 die(_("Cannot move bottom win"));
1267#endif /* HAVE_WRESIZE */
1268#endif /* HAVE_NCURSES_H */
1269
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001270 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001271
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001272 if (current_y > editwinrows - 1) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001273 edit_update(editbot);
1274 }
1275 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001276
1277 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001278 refresh();
Chris Allegretta97accc62000-06-19 05:45:52 +00001279 titlebar();
1280 edit_refresh();
1281 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001282 total_refresh();
1283#endif
1284}
1285
1286int do_tab(void)
1287{
1288 do_char('\t');
1289 return 1;
1290}
1291
1292#ifndef NANO_SMALL
1293int empty_line(const char *data)
1294{
1295 while (*data) {
1296 if (!isspace(*data))
1297 return 0;
1298
1299 data++;
1300 }
1301
1302 return 1;
1303}
1304
1305int no_spaces(const char *data)
1306{
1307 while (*data) {
1308 if (isspace(*data))
1309 return 0;
1310
1311 data++;
1312 }
1313
1314 return 1;
1315}
1316
1317void justify_format(char *data)
1318{
1319 int i = 0;
1320 int len = strlen(data);
1321
1322 /* Skip first character regardless and leading whitespace. */
1323 for (i = 1; i < len; i++) {
1324 if (!isspace(data[i]))
1325 break;
1326 }
1327
1328 i++; /* (i) is now at least 2. */
1329
1330 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
1331 for (; i < len; i++) {
1332 if (isspace(data[i]) && isspace(data[i - 1])
1333 && (data[i - 2] != '.')) {
1334 memmove(data + i, data + i + 1, len - i);
1335 len--;
1336 i--;
1337 }
1338 }
1339}
1340#endif
1341
1342int do_justify(void)
1343{
1344#ifndef NANO_SMALL
1345 int slen = 0; /* length of combined lines on one line. */
1346 int initial_y;
1347 filestruct *initial = NULL;
1348
1349 if (empty_line(current->data)) {
1350 /* Justify starting at first non-empty line. */
1351 do {
1352 if (!current->next)
1353 return 1;
1354
1355 current = current->next;
1356 current_y++;
1357 }
1358 while (empty_line(current->data));
1359 } else {
1360 /* Search back for the beginning of the paragraph, where
1361 * Paragraph is 1) A line with leading whitespace
1362 * or 2) A line following an empty line.
1363 */
1364 while (current->prev != NULL) {
1365 if (isspace(current->data[0]) || !current->data[0])
1366 break;
1367
1368 current = current->prev;
1369 current_y--;
1370 }
1371
1372 /* First line with leading whitespace may be empty. */
1373 if (empty_line(current->data)) {
1374 if (current->next) {
1375 current = current->next;
1376 current_y++;
1377 } else
1378 return 1;
1379 }
1380 }
1381 initial = current;
1382 initial_y = current_y;
1383
1384 set_modified();
1385 /* Put the whole paragraph into one big line. */
1386 while (current->next && !isspace(current->next->data[0])
1387 && current->next->data[0]) {
1388 filestruct *tmpnode = current->next;
1389 int len = strlen(current->data);
1390 int len2 = strlen(current->next->data);
1391
1392 /* length of both strings plus space between strings and ending \0. */
1393 current->data = nrealloc(current->data, len + len2 + 2);
1394 current->data[len++] = ' ';
1395 current->data[len] = '\0';
1396
1397 strncat(current->data, current->next->data, len2);
1398
1399 unlink_node(tmpnode);
1400 delete_node(tmpnode);
1401
1402 }
1403
1404 justify_format(current->data);
1405
1406 slen = strlen(current->data);
Adam Rogoyski09f97962000-06-20 02:50:33 +00001407 while ((strlenpt(current->data) > (fill))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001408 && !no_spaces(current->data)) {
1409 int i = 0;
1410 int len2 = 0;
1411 filestruct *tmpline = nmalloc(sizeof(filestruct));
1412
Adam Rogoyski09f97962000-06-20 02:50:33 +00001413 /* Start at fill , unless line isn't that long (but it appears at least
1414 * fill long with tabs.
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001415 */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001416 if (slen > fill)
1417 i = fill;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001418 else
1419 i = slen;
1420 for (; i > 0; i--) {
1421 if (isspace(current->data[i]) &&
1422 ((strlenpt(current->data) - strlen(current->data + i)) <=
1423 fill)) break;
1424 }
1425 if (!i)
1426 break;
1427
1428 current->data[i] = '\0';
1429
1430 len2 = strlen(current->data + i + 1);
1431 tmpline->data = nmalloc(len2 + 1);
1432
1433 /* Skip the white space in current. */
1434 memcpy(tmpline->data, current->data + i + 1, len2);
1435 tmpline->data[len2] = '\0';
1436
1437 current->data = nrealloc(current->data, i + 1);
1438
1439 tmpline->prev = current;
1440 tmpline->next = current->next;
1441 if (current->next != NULL)
1442 current->next->prev = tmpline;
1443
1444 current->next = tmpline;
1445 current = tmpline;
1446 slen -= i + 1;
1447 current_y++;
1448 }
1449
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001450
1451 if (current->next)
1452 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00001453 else
1454 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001455 current_x = 0;
1456 placewewant = 0;
1457
Adam Rogoyski09f97962000-06-20 02:50:33 +00001458 renumber(initial);
1459 totlines = filebot->lineno;
1460
1461 werase(edit);
1462
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001463 if ((current_y < 0) || (current_y >= editwinrows - 1)
1464 || (initial_y <= 0)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001465 edit_update(current);
1466 center_cursor();
1467 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001468 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001469 }
1470
Adam Rogoyski09f97962000-06-20 02:50:33 +00001471
1472 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001473 statusbar("Justify Complete");
1474 return 1;
1475#else
1476 nano_small_msg();
1477 return 1;
1478#endif
1479}
1480
1481
1482void help_init(void)
1483{
1484 int i, sofar = 0;
1485 long allocsize = 1; /* How much space we're gonna need for the help text */
1486 char buf[BUFSIZ];
1487
1488 /* Compute the space needed for the shortcut lists - we add 15 to
1489 have room for the shortcut abbrev and its possible alternate keys */
1490 for (i = 0; i < MAIN_LIST_LEN; i++)
1491 if (main_list[i].help != NULL)
1492 allocsize += strlen(main_list[i].help) + 15;
1493
1494 allocsize += strlen(help_text_init);
1495
1496 if (help_text != NULL)
1497 free(help_text);
1498
1499 /* Allocate space for the help text */
1500 help_text = nmalloc(allocsize);
1501
1502 /* Now add the text we want */
1503 strcpy(help_text, help_text_init);
1504
1505 /* Now add our shortcut info */
1506 for (i = 0; i < MAIN_LIST_LEN; i++) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001507 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001508
1509 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00001510 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001511 main_list[i].misc1 - KEY_F0);
1512 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001513 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001514
1515 if (main_list[i].altval > 0)
Robert Siemborski6af14312000-07-01 21:34:26 +00001516 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(@%c) ",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001517 main_list[i].altval - 32);
1518 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001519 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001520
1521 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00001522 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001523
1524 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00001525 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001526 }
1527
1528}
1529
1530int main(int argc, char *argv[])
1531{
1532 int optchr;
1533 int kbinput; /* Input from keyboard */
1534 long startline = 0; /* Line to try and start at */
1535 struct sigaction act; /* For our lovely signals */
1536 int keyhandled = 0; /* Have we handled the keystroke yet? */
1537 int tmpkey = 0, i;
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001538#ifdef HAVE_TABSIZE
1539 int usrtabsize = 0; /* User defined tab size */
1540#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001541 char *argv0;
1542 struct termios term;
1543
1544#ifdef HAVE_GETOPT_LONG
1545 int option_index = 0;
1546 struct option long_options[] = {
Chris Allegretta47805612000-07-07 02:35:34 +00001547#ifdef _POSIX_VERSION
Chris Allegretta9fc8d432000-07-07 01:49:52 +00001548 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00001549#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001550 {"version", 0, 0, 'V'},
1551 {"const", 0, 0, 'c'},
1552 {"suspend", 0, 0, 'z'},
1553 {"nowrap", 0, 0, 'w'},
1554 {"nohelp", 0, 0, 'x'},
1555 {"help", 0, 0, 'h'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00001556#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00001557 {"cut", 0, 0, 'k'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00001558#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001559 {"autoindent", 0, 0, 'i'},
1560 {"tempfile", 0, 0, 't'},
1561 {"speller", 1, 0, 's'},
1562 {"fill", 1, 0, 'r'},
1563 {"mouse", 0, 0, 'm'},
1564 {"pico", 0, 0, 'p'},
1565 {"nofollow", 0, 0, 'l'},
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001566#ifdef HAVE_TABSIZE
1567 {"tabsize", 0, 0, 'T'},
1568#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001569 {0, 0, 0, 0}
1570 };
1571#endif
1572
1573 /* Flag inits... */
1574 SET(FOLLOW_SYMLINKS);
1575
1576#ifndef NANO_SMALL
1577 setlocale(LC_ALL, "");
1578 bindtextdomain(PACKAGE, LOCALEDIR);
1579 textdomain(PACKAGE);
1580#endif
1581
1582#ifdef HAVE_GETOPT_LONG
Chris Allegretta627de192000-07-12 02:09:17 +00001583 while ((optchr = getopt_long(argc, argv, "?T:RVchiklmpr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001584 long_options, &option_index)) != EOF) {
1585#else
Chris Allegretta627de192000-07-12 02:09:17 +00001586 while ((optchr = getopt(argc, argv, "h?T:RVciklmpr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001587#endif
1588
1589 switch (optchr) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001590#ifdef HAVE_TABSIZE
1591 case 'T':
1592 usrtabsize = atoi(optarg);
1593 if (usrtabsize <= 0) {
1594 usage(); /* To stop bogus data for tab width */
1595 finish(1);
1596 }
1597 break;
1598#else
1599 case 'T':
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001600 usage(); /* Oops! You dont really have that option */
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001601 finish(1);
1602#endif
Chris Allegretta47805612000-07-07 02:35:34 +00001603#ifdef _POSIX_VERSION
Chris Allegretta9fc8d432000-07-07 01:49:52 +00001604 case 'R':
1605 SET(USE_REGEXP);
1606 break;
Chris Allegretta47805612000-07-07 02:35:34 +00001607#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001608 case 'V':
1609 version();
1610 exit(0);
1611 case 'c':
1612 SET(CONSTUPDATE);
1613 break;
1614 case 'h':
1615 case '?':
1616 usage();
1617 exit(0);
1618 case 'i':
1619 SET(AUTOINDENT);
1620 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00001621#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00001622 case 'k':
1623 SET(CUT_TO_END);
1624 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00001625#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001626 case 'l':
1627 UNSET(FOLLOW_SYMLINKS);
1628 break;
1629 case 'm':
1630 SET(USE_MOUSE);
1631 break;
1632 case 'p':
1633 SET(PICO_MSGS);
1634 break;
1635 case 'r':
1636 fill = atoi(optarg);
1637 if (fill <= 0) {
1638 usage(); /* To stop bogus data (like a string) */
1639 finish(1);
1640 }
1641 break;
1642 case 's':
1643 alt_speller = nmalloc(strlen(optarg) + 1);
1644 strcpy(alt_speller, optarg);
1645 break;
1646 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00001647 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001648 break;
1649 case 'v':
1650 SET(VIEW_MODE);
1651 break;
1652 case 'w':
1653 SET(NO_WRAP);
1654 break;
1655 case 'x':
1656 SET(NO_HELP);
1657 break;
1658 case 'z':
1659 SET(SUSPEND);
1660 break;
1661 default:
1662 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001663 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001664 }
1665
1666 }
1667
1668 argv0 = strrchr(argv[0], '/');
1669 if ((argv0 && strstr(argv0, "pico"))
1670 || (!argv0 && strstr(argv[0], "pico")))
1671 SET(PICO_MSGS);
1672
1673 filename = nmalloc(PATH_MAX);
1674 strcpy(filename, "");
1675
1676 /* See if there's a non-option in argv (first non-option is the
1677 filename, if +LINE is not given) */
1678 if (argc == 1 || argc <= optind)
1679 strcpy(filename, "");
1680 else {
1681 /* Look for the +line flag... */
1682 if (argv[optind][0] == '+') {
1683 startline = atoi(&argv[optind][1]);
1684 optind++;
1685 if (argc == 1 || argc <= optind)
1686 strcpy(filename, "");
1687 else
1688 strncpy(filename, argv[optind], 132);
1689 } else
1690 strncpy(filename, argv[optind], 132);
1691
1692 }
1693
1694
1695 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001696 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001697
1698 /* Adam's code to blow away intr character so ^C can show cursor pos */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001699 tcgetattr(0, &term);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001700 for (i = 0; i < NCCS; i++) {
1701 if (term.c_cc[i] == CINTR || term.c_cc[i] == CQUIT)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001702 term.c_cc[i] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001703 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001704 tcsetattr(0, TCSANOW, &term);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001705
1706 /* now ncurses init stuff... */
1707 initscr();
1708 savetty();
1709 nonl();
1710 cbreak();
1711 noecho();
1712 timeout(0);
1713
1714 /* Set up some global variables */
1715 global_init();
1716 shortcut_init();
1717 init_help_msg();
1718 help_init();
1719
1720 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001721 memset(&act, 0, sizeof(struct sigaction));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001722 act.sa_handler = SIG_IGN;
1723 sigaction(SIGINT, &act, NULL);
1724 sigaction(SIGQUIT, &act, NULL);
1725
1726 if (!ISSET(SUSPEND))
1727 sigaction(SIGTSTP, &act, NULL);
1728
1729 /* Trap SIGHUP cuz we want to write the file out. */
1730 act.sa_handler = handle_hup;
1731 sigaction(SIGHUP, &act, NULL);
1732
1733 act.sa_handler = handle_sigwinch;
1734 sigaction(SIGWINCH, &act, NULL);
1735
1736#ifdef DEBUG
1737 fprintf(stderr, _("Main: set up windows\n"));
1738#endif
1739
1740 /* Setup up the main text window */
1741 edit = newwin(editwinrows, COLS, 2, 0);
1742 keypad(edit, TRUE);
1743
1744#ifndef NANO_SMALL
1745#ifdef NCURSES_MOUSE_VERSION
1746 if (ISSET(USE_MOUSE)) {
1747 mousemask(BUTTON1_RELEASED, NULL);
1748 mouseinterval(50);
1749 }
1750#endif
1751#endif
1752
1753 /* And the other windows */
1754 topwin = newwin(2, COLS, 0, 0);
1755 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
1756 keypad(bottomwin, TRUE);
1757
1758#ifdef DEBUG
1759 fprintf(stderr, _("Main: bottom win\n"));
1760#endif
1761 /* Set up up bottom of window */
1762 display_main_list();
1763
1764#ifdef DEBUG
1765 fprintf(stderr, _("Main: open file\n"));
1766#endif
1767
1768 titlebar();
1769 if (argc == 1)
1770 new_file();
1771 else
1772 open_file(filename, 0, 0);
1773
1774 if (startline > 0)
1775 do_gotoline(startline);
1776 else
1777 edit_update(fileage);
1778
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001779#ifdef HAVE_TABSIZE
1780 if (usrtabsize > 0)
1781 TABSIZE = usrtabsize;
1782#endif
1783
Robert Siemborski6967eec2000-07-08 14:23:32 +00001784 edit_refresh();
1785 reset_cursor();
1786
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001787 while (1) {
1788 kbinput = wgetch(edit);
1789 if (kbinput == 27) { /* Grab Alt-key stuff first */
1790 switch (kbinput = wgetch(edit)) {
1791 case 91:
1792
1793 switch (kbinput = wgetch(edit)) {
1794 case 'A':
1795 kbinput = KEY_UP;
1796 break;
1797 case 'B':
1798 kbinput = KEY_DOWN;
1799 break;
1800 case 'C':
1801 kbinput = KEY_RIGHT;
1802 break;
1803 case 'D':
1804 kbinput = KEY_LEFT;
1805 break;
1806 case 'H':
1807 kbinput = KEY_HOME;
1808 break;
1809 case 'F':
1810 kbinput = KEY_END;
1811 break;
1812 case 49: /* X window F-keys */
1813 tmpkey = wgetch(edit);
1814 kbinput = KEY_F(tmpkey) - 48;
1815 wgetch(edit); /* Junk character */
1816 break;
1817 case 53: /* page up */
1818 kbinput = KEY_PPAGE;
1819 if ((kbinput = wgetch(edit)) == 126)
1820 kbinput = KEY_PPAGE; /* Ignore extra tilde */
1821 else { /* I guess this could happen ;-) */
1822 ungetch(kbinput);
1823 continue;
1824 }
1825 break;
1826 case 54: /* page down */
1827 kbinput = KEY_NPAGE;
1828 if ((kbinput = wgetch(edit)) == 126)
1829 kbinput = KEY_NPAGE; /* Same thing here */
1830 else {
1831 ungetch(kbinput);
1832 continue;
1833 }
1834 break;
1835
1836 default:
1837#ifdef DEBUG
1838 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
1839 kbinput, kbinput);
1840#endif
1841 break;
1842 }
1843 break;
1844 default:
1845
1846 /* Check for the altkey defs.... */
1847 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
1848 if (kbinput == main_list[i].altval ||
1849 kbinput == main_list[i].altval - 32) {
1850 kbinput = main_list[i].val;
1851 break;
1852 }
1853#ifdef DEBUG
1854 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
1855 kbinput);
1856#endif
1857 break;
1858 }
1859 }
1860 /* Look through the main shortcut list to see if we've hit a
1861 shortcut key */
1862 for (i = 0; i < MAIN_LIST_LEN; i++) {
1863 if (kbinput == main_list[i].val ||
1864 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
1865 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
1866 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
1867 print_view_warning();
1868 else
1869 main_list[i].func();
1870 keyhandled = 1;
1871 }
1872 }
1873 /* Last gasp, stuff that's not in the main lists */
1874 if (!keyhandled)
1875 switch (kbinput) {
1876#ifndef NANO_SMALL
1877#ifdef NCURSES_MOUSE_VERSION
1878 case KEY_MOUSE:
1879 do_mouse();
1880 break;
1881#endif
1882#endif
1883 case 0: /* Erg */
1884 do_next_word();
1885 break;
1886 case 331: /* Stuff that we don't want to do squat */
1887 case -1:
1888 case 410: /* Must ignore this, it gets sent when we resize */
1889 break;
1890 default:
1891#ifdef DEBUG
1892 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
1893#endif
1894 /* We no longer stop unhandled sequences so that people with
1895 odd character sets can type... */
1896
1897 if (ISSET(VIEW_MODE)) {
1898 print_view_warning();
1899 break;
1900 }
1901 do_char(kbinput);
1902 }
1903 if (ISSET(CONSTUPDATE))
1904 do_cursorpos();
1905
1906 reset_cursor();
1907 wrefresh(edit);
1908 keyhandled = 0;
1909 }
1910
1911 getchar();
1912 finish(0);
1913
1914}