blob: b0747150b52aea573f71c4cda33f5bc8dd420a41 [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 */
Chris Allegretta8f6c0692000-07-19 01:16:18 +000061char *last_search = "\0"; /* Last string we searched for */
62char *last_replace = "\0"; /* 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 Allegretta6925bbd2000-07-28 01:41:29 +0000310/* Null a string at a certain index and align it */
311void null_at(char *data, int index)
312{
313 data[index] = 0;
314 align(&data);
315}
316
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000317void usage(void)
318{
319#ifdef HAVE_GETOPT_LONG
320 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
321 printf(_("Option Long option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000322#ifdef HAVE_TABSIZE
323 printf(_
324 (" -T --tabsize=[num] Set width of a tab to num\n"));
325#endif
Chris Allegretta47805612000-07-07 02:35:34 +0000326#ifdef _POSIX_VERSION
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000327 printf(_
328 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000329#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000330 printf
331 (_
332 (" -V --version Print version information and exit\n"));
333 printf(_
334 (" -c --const Constantly show cursor position\n"));
335 printf(_
336 (" -h --help Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000337#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000338 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000339 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000340#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000341 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000342 (" -i --autoindent Automatically indent new lines\n"));
343 printf(_
344 (" -l --nofollow Don't follow symbolic links, overwrite.\n"));
345#ifndef NANO_SMALL
346#ifdef NCURSES_MOUSE_VERSION
347 printf(_(" -m --mouse Enable mouse\n"));
348#endif
349#endif
350 printf
351 (_
352 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
353 printf(_
354 (" -p --pico Make bottom 2 lines more Pico-like\n"));
355 printf(_
356 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
357 printf(_
358 (" -t --tempfile Auto save on exit, don't prompt\n"));
359 printf(_
360 (" -v --view View (read only) mode\n"));
361 printf(_
362 (" -w --nowrap Don't wrap long lines\n"));
363 printf(_
364 (" -x --nohelp Don't show help window\n"));
365 printf(_
366 (" -z --suspend Enable suspend\n"));
367 printf(_
368 (" +LINE Start at line number LINE\n"));
369#else
370 printf(_("Usage: nano [option] +LINE <file>\n\n"));
371 printf(_("Option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000372#ifdef HAVE_TABSIZE
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000373 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000374#endif
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000375 printf(_(" -R Use regular expressions for search\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000376 printf(_(" -V Print version information and exit\n"));
377 printf(_(" -c Constantly show cursor position\n"));
378 printf(_(" -h Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000379#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +0000380 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000381#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000382 printf(_(" -i Automatically indent new lines\n"));
383 printf(_
384 (" -l Don't follow symbolic links, overwrite.\n"));
385#ifndef NANO_SMALL
386#ifdef NCURSES_MOUSE_VERSION
387 printf(_(" -m Enable mouse\n"));
388#endif
389#endif
390 printf(_
391 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
392 printf(_(" -s [prog] Enable alternate speller\n"));
393 printf(_(" -p Make bottom 2 lines more Pico-like\n"));
394 printf(_(" -t Auto save on exit, don't prompt\n"));
395 printf(_(" -v View (read only) mode\n"));
396 printf(_(" -w Don't wrap long lines\n"));
397 printf(_(" -x Don't show help window\n"));
398 printf(_(" -z Enable suspend\n"));
399 printf(_(" +LINE Start at line number LINE\n"));
400#endif
401 exit(0);
402}
403
404void version(void)
405{
406 printf(_(" nano version %s by Chris Allegretta (compiled %s, %s)\n"),
407 VERSION, __TIME__, __DATE__);
408 printf(_(" Email: nano@asty.org Web: http://www.asty.org/nano\n"));
409}
410
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000411filestruct *make_new_node(filestruct * prevnode)
412{
413 filestruct *newnode;
414
415 newnode = nmalloc(sizeof(filestruct));
416 newnode->data = NULL;
417
418 newnode->prev = prevnode;
419 newnode->next = NULL;
420
421 if (prevnode != NULL)
422 newnode->lineno = prevnode->lineno + 1;
423
424 return newnode;
425}
426
Chris Allegretta7975ed82000-07-28 00:58:35 +0000427/* Splice a node into an existing filestruct */
428void splice_node(filestruct *begin, filestruct *new, filestruct *end)
429{
430 new->next = end;
431 new->prev = begin;
432 begin->next = new;
433 if (end != NULL)
434 end->prev = new;
435}
436
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000437int do_mark()
438{
439#ifdef NANO_SMALL
440 nano_small_msg();
441#else
442 if (!ISSET(MARK_ISSET)) {
443 statusbar(_("Mark Set"));
444 SET(MARK_ISSET);
445 mark_beginbuf = current;
446 mark_beginx = current_x;
447 } else {
448 statusbar(_("Mark UNset"));
449 UNSET(MARK_ISSET);
450 mark_beginbuf = NULL;
451 mark_beginx = 0;
452
453 edit_refresh();
454 }
455#endif
456 return 1;
457}
458
459int no_help(void)
460{
461 if ISSET
462 (NO_HELP)
463 return 2;
464 else
465 return 0;
466}
467
468void nano_small_msg(void)
469{
470 statusbar("Sorry, this function not available with nano-tiny option");
471}
472
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000473/* The user typed a printable character; add it to the edit buffer */
474void do_char(char ch)
475{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000476 /* magic-line: when a character is inserted on the current magic line,
477 * it means we need a new one! */
478 if(filebot == current && current->data[0] == '\0') {
479 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000480 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000481 }
482
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000483 /* More dangerousness fun =) */
484 current->data = nrealloc(current->data, strlen(current->data) + 2);
485 memmove(&current->data[current_x + 1],
486 &current->data[current_x],
487 strlen(current->data) - current_x + 1);
488 current->data[current_x] = ch;
489 do_right();
490
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000491 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000492 check_wrap(current, ch);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000493 set_modified();
494 check_statblank();
495 UNSET(KEEP_CUTBUFFER);
496 totsize++;
497
498}
499
500/* Someone hits return *gasp!* */
501int do_enter(filestruct * inptr)
502{
503 filestruct *new;
504 char *tmp, *spc;
505 int extra = 0;
506
507 new = make_new_node(inptr);
508 tmp = &current->data[current_x];
509 current_x = 0;
510
511 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
512 if (ISSET(AUTOINDENT)) {
513 spc = current->data;
514 if (spc) {
515 while ((*spc == ' ') || (*spc == '\t')) {
516 extra++;
517 spc++;
518 current_x++;
519 }
520 new->data = nmalloc(strlen(tmp) + extra + 1);
521 strncpy(new->data, current->data, extra);
522 strcpy(&new->data[extra], tmp);
523 }
524 } else {
525 new->data = nmalloc(strlen(tmp) + 1);
526 strcpy(new->data, tmp);
527 }
528 *tmp = 0;
529
Chris Allegretta7975ed82000-07-28 00:58:35 +0000530 if (inptr->next != NULL) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000531 filebot = new;
532 editbot = new;
533 }
Chris Allegretta7975ed82000-07-28 00:58:35 +0000534 splice_node(inptr, new, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000535
536 totsize++;
537 renumber(current);
538 current = new;
539 align(&current->data);
540
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000541 /* The logic here is as follows:
542 * -> If we are at the bottom of the buffer, we want to recenter
543 * (read: rebuild) the screen and forcably move the cursor.
544 * -> otherwise, we want simply to redraw the screen and update
545 * where we think the cursor is.
546 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000547 if (current_y == editwinrows - 1) {
548 edit_update(current);
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000549 reset_cursor();
550 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000551 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000552 edit_refresh();
553 update_cursor();
554 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000555
556 totlines++;
557 set_modified();
558
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000559 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000560 return 1;
561}
562
563int do_enter_void(void)
564{
565 return do_enter(current);
566}
567
568void do_next_word(void)
569{
570 filestruct *fileptr;
571 int i;
572
573 if (current == NULL)
574 return;
575
576 i = current_x;
577 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
578 if (fileptr == current) {
579 while (isalnum((int) fileptr->data[i])
580 && fileptr->data[i] != 0)
581 i++;
582
583 if (fileptr->data[i] == 0) {
584 i = 0;
585 continue;
586 }
587 }
588 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
589 i++;
590
591 if (fileptr->data[i] != 0)
592 break;
593
594 i = 0;
595 }
596 if (fileptr == NULL)
597 current = filebot;
598 else
599 current = fileptr;
600
601 current_x = i;
602 placewewant = xplustabs();
603 if (current->lineno >= editbot->lineno)
604 edit_update(current);
605
606}
607
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000608void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000609{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000610 int i = 0; /* Index into ->data for line. */
611 int i_tabs = 0; /* Screen position of ->data[i]. */
612 int last_word_end = -1; /* Location of end of last word found. */
613 int current_word_start = -1; /* Location of start of current word. */
614 int current_word_start_t = -1; /* Location of start of current word screen position. */
615 int current_word_end = -1; /* Location of end of current word */
616 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000617 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000618
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000619 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000620 int right = 0;
621 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000622
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000623 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000624
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000625 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000626 if (!isspace(inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000627 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000628
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000629 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000630 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000631
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000632 while (!isspace(inptr->data[i]) && inptr->data[i]) {
633 i++;
634 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000635 if (inptr->data[i] < 32)
636 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000637 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000638
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000639 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000640 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000641 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000642 } else {
643 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000644 current_word_end_t = i_tabs - 1;
645 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000646 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000647
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000648 if (inptr->data[i] == NANO_CONTROL_I) {
649 if (i_tabs % TABSIZE != 0);
650 i_tabs += TABSIZE - (i_tabs % TABSIZE);
651 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000652
Adam Rogoyski09f97962000-06-20 02:50:33 +0000653 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000654 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000655 }
656
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000657 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000658 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000659 * a) one word takes up the whole line with no starting spaces.
660 * - do nothing and return.
661 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000662 * - word starts new line.
663 * - keep white space on original line up to the cursor.
664 * *) cursor is after word at wrap point
665 * - either it's all white space after word, and this routine isn't called.
666 * - or we are actually in case 2 (2 words).
667 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000668 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000669 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000670 * - white space at end of original line is cleared, unless
671 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000672 * b) cursor is at the word at the wrap point.
673 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000674 * 1. pressed a space and at first character of wrap point word.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000675 * - white space on original line is kept to where cursor was.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000676 * 2. pressed non space (or space elsewhere).
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000677 * - white space at end of original line is cleared.
678 * c) cursor is past the word at the wrap point.
679 * - word at wrap point starts a new line.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000680 * - white space at end of original line is cleared
681 */
682
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000683 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000684
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000685 /* Category 1a: one word taking up the whole line with no beginning spaces. */
686 if ((last_word_end == -1) && (!isspace(inptr->data[0]))) {
687 for (i = current_word_end; i < len; i++) {
688 if (!isspace(inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000689 current_word_start = i;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000690 while (!isspace(inptr->data[i]) && (i < len)) {
691 i++;
692 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000693 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000694 current_word_end = i;
695 break;
696 }
697 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000698
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000699 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000700 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000701 return;
702 }
703 if (current_x >= last_word_end) {
704 right = (current_x - current_word_start) + 1;
705 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000706 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000707 }
708
709 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
710 strcpy(temp->data, &inptr->data[current_word_start]);
711 inptr->data = nrealloc(inptr->data, last_word_end + 2);
712 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000713 } else
714 /* Category 1b: one word on the line and word not taking up whole line
715 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000716 if (last_word_end == -1) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000717 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
718 strcpy(temp->data, &inptr->data[current_word_start]);
719
720 /* Inside word, remove it from original, and move cursor to right spot. */
721 if (current_x >= current_word_start) {
722 right = current_x - current_word_start;
723 current_x = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000724 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000725 }
726
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000727 null_at(inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000728
729 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
730 mark_beginbuf = temp;
731 mark_beginx = 0;
732 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000733 }
734
735 /* Category 2: two or more words on the line. */
736 else {
737
738 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000739 if (current_x < current_word_start) {
740 temp->data =
741 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
742 strcpy(temp->data, &inptr->data[current_word_start]);
743
744 if (!isspace(input_char)) {
745 i = current_word_start - 1;
746 while (isspace(inptr->data[i])) {
747 i--;
748 assert(i >= 0);
749 }
750 } else if (current_x <= last_word_end)
751 i = last_word_end - 1;
752 else
753 i = current_x;
754
755 inptr->data = nrealloc(inptr->data, i + 2);
756 inptr->data[i + 1] = 0;
757 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000758
759
760 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000761 else if ((current_x >= current_word_start)
762 && (current_x <= (current_word_end + 1))) {
763 temp->data =
764 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000765 strcpy(temp->data, &inptr->data[current_word_start]);
766
767 down = 1;
768
769 right = current_x - current_word_start;
770 i = current_word_start - 1;
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000771 if (isspace(input_char) && (current_x == current_word_start)) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000772 current_x = current_word_start;
773
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000774 null_at(inptr->data, current_word_start);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000775 } else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000776
777 while (isspace(inptr->data[i])) {
778 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000779 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000780 }
781 inptr->data = nrealloc(inptr->data, i + 2);
782 inptr->data[i + 1] = 0;
783 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000784 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000785
786
787 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000788 else {
789 temp->data =
790 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000791 strcpy(temp->data, &inptr->data[current_word_start]);
792
793 down = 1;
794 right = current_x - current_word_start;
795
796 current_x = current_word_start;
797 i = current_word_start - 1;
798
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000799 while (isspace(inptr->data[i])) {
800 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000801 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000802 inptr->data = nrealloc(inptr->data, i + 2);
803 inptr->data[i + 1] = 0;
804 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000805 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000806 }
807
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000808 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000809 if (ISSET(SAMELINEWRAP) && inptr->next) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000810 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
811 char *p =
812 nmalloc(strlen(temp->data) + strlen(inptr->next->data) + 2);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000813 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000814
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000815 strcpy(p, temp->data);
816 strcat(p, " ");
817 strcat(p, inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000818
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000819 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000820 inptr->next->data = p;
821
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000822 free(temp->data);
823 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000824
825
826 /* The next line line may need to be wrapped as well. */
827 current_y = old_y + 1;
828 current_x = strlen(inptr->next->data);
829 while (current_x >= 0) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000830 if (isspace(inptr->next->data[current_x])
831 && (current_x < fill)) break;
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000832 current_x--;
833 }
834 if (current_x >= 0)
835 check_wrap(inptr->next, ' ');
836
837 current_x = old_x;
838 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000839 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000840 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000841 else {
842 temp->prev = inptr;
843 temp->next = inptr->next;
844
845 if (inptr->next)
846 inptr->next->prev = temp;
847 inptr->next = temp;
848
849 if (!temp->next)
850 filebot = temp;
851
852 SET(SAMELINEWRAP);
853 }
854
855
856 totlines++;
Robert Siemborskia417ddc2000-07-24 23:18:48 +0000857 /* Everything about it makes me want this line here but it causes
858 * totsize to be high by one for some reason. Sigh. (Rob) */
859 /* totsize++; */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000860
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000861 renumber(inptr);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000862 edit_update_top(edittop);
863
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000864
865 /* Move the cursor to the new line if appropriate. */
866 if (down) {
867 do_right();
868 }
869
870 /* Move the cursor to the correct spot in the line if appropriate. */
871 while (right--) {
872 do_right();
873 }
874
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000875 edit_update_top(edittop);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000876 reset_cursor();
877 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000878}
879
880/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000881void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000882{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000883 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000884#ifdef DEBUG
885 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
886 inptr->data);
887#endif
888
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000889 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000890 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000891 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000892 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000893
894 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000895 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000896
Adam Rogoyski09f97962000-06-20 02:50:33 +0000897 while (isspace(inptr->data[i]) && inptr->data[i])
898 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000899
Adam Rogoyski09f97962000-06-20 02:50:33 +0000900 if (!inptr->data[i])
901 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000902
Adam Rogoyski09f97962000-06-20 02:50:33 +0000903 /* String must be at least 1 character long. */
904 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
905 if (isspace(inptr->data[i])) {
906 if (!char_found)
907 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000908 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000909 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000910 } else
911 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000912 }
Adam Rogoyski09f97962000-06-20 02:50:33 +0000913
914 if (char_found == 2)
915 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000916 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000917}
918
919/* Stuff we do when we abort from programs and want to clean up the
920 * screen. This doesnt do much right now.
921 */
922void do_early_abort(void)
923{
924 blank_statusbar_refresh();
925}
926
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000927int do_backspace(void)
928{
929 filestruct *previous, *tmp;
930
931 if (current_x != 0) {
932 /* Let's get dangerous */
933 memmove(&current->data[current_x - 1], &current->data[current_x],
934 strlen(current->data) - current_x + 1);
935#ifdef DEBUG
936 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
937#endif
938 align(&current->data);
939 do_left();
940 } else {
941 if (current == fileage)
942 return 0; /* Can't delete past top of file */
943
944 previous = current->prev;
945 current_x = strlen(previous->data);
946 previous->data = nrealloc(previous->data,
947 strlen(previous->data) +
948 strlen(current->data) + 1);
949 strcat(previous->data, current->data);
950
951 tmp = current;
952 unlink_node(current);
953 delete_node(current);
954 if (current == edittop) {
955 if (previous->next)
956 current = previous->next;
957 else
958 current = previous;
959 page_up();
960 } else {
961 if (previous->next)
962 current = previous->next;
963 else
964 current = previous;
965 update_line(current, current_x);
966 }
967
968 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000969 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000970 filebot = current;
971 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +0000972
973 /* Recreate the magic line if we're deleting it AND if the
974 line we're on now is NOT blank. if it is blank we
975 can just use IT for the magic line. This is how Pico
976 appears to do it, in any case */
977 if (strcmp(current->data, "")) {
978 new_magicline();
979 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +0000980 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +0000981 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000982 }
983
984 current = previous;
985 renumber(current);
986 previous_line();
987 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000988#ifdef DEBUG
989 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
990#endif
991
992 }
993
994 totsize--;
995 set_modified();
996 UNSET(KEEP_CUTBUFFER);
997 edit_refresh();
998 return 1;
999}
1000
1001int do_delete(void)
1002{
1003 filestruct *foo;
1004
1005 if (current_x != strlen(current->data)) {
1006 /* Let's get dangerous */
1007 memmove(&current->data[current_x], &current->data[current_x + 1],
1008 strlen(current->data) - current_x);
1009
1010 align(&current->data);
1011
1012 } else if (current->next != NULL) {
1013 current->data = nrealloc(current->data,
1014 strlen(current->data) +
1015 strlen(current->next->data) + 1);
1016 strcat(current->data, current->next->data);
1017
1018 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001019 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001020 filebot = current;
1021 editbot = current;
1022 }
1023
1024 unlink_node(foo);
1025 delete_node(foo);
1026 update_line(current, current_x);
1027
Chris Allegretta28a0f892000-07-05 22:47:54 +00001028 /* Please see the comment in do_basckspace if you don't understand
1029 this test */
1030 if (current == filebot && strcmp(current->data, ""))
1031 {
1032 new_magicline();
1033 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001034 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001035 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001036 renumber(current);
1037 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001038 } else
1039 return 0;
1040
1041 totsize--;
1042 set_modified();
1043 UNSET(KEEP_CUTBUFFER);
1044 edit_refresh();
1045 return 1;
1046}
1047
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001048void wrap_reset(void)
1049{
1050 UNSET(SAMELINEWRAP);
1051}
1052
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001053/* Stuff we want to do when we exit the spell program one of its many ways */
1054void exit_spell(char *tmpfilename, char *foo)
1055{
1056 free(foo);
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001057
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001058 if (remove(tmpfilename) == -1)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001059 statusbar(_("Error deleting tempfile, ack!"));
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001060 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001061}
1062
1063/*
1064 * This is Chris' very ugly spell function. Someone please make this
1065 * better =-)
1066 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001067int do_spell(void)
1068{
Chris Allegretta67105eb2000-07-03 03:18:32 +00001069#ifdef NANO_SMALL
1070 nano_small_msg();
1071 return 1;
1072#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001073 char *temp, *foo;
Robert Siemborski6af14312000-07-01 21:34:26 +00001074 int i, size;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001075
1076 if ((temp = tempnam(0, "nano.")) == NULL) {
1077 statusbar(_("Could not create a temporary filename: %s"),
1078 strerror(errno));
1079 return 0;
1080 }
1081 if (write_file(temp, 1) == -1)
1082 return 0;
1083
1084 if (alt_speller) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001085 size = strlen(temp) + strlen(alt_speller) + 2;
1086 foo = nmalloc(size);
1087 snprintf(foo, size, "%s %s", alt_speller, temp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001088 } else {
1089
1090 /* For now, we only try ispell because we're not capable of
1091 handling the normal spell program (yet...) */
Robert Siemborski6af14312000-07-01 21:34:26 +00001092 size = strlen(temp) + 8;
1093 foo = nmalloc(size);
1094 snprintf(foo, size, "ispell %s", temp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001095 }
1096
1097 endwin();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001098 if (alt_speller) {
1099 if ((i = system(foo)) == -1 || i == 32512) {
1100 statusbar(_("Could not invoke spell program \"%s\""),
1101 alt_speller);
1102 exit_spell(temp, foo);
1103 return 0;
1104 }
1105 } else if ((i = system(foo)) == -1 || i == 32512) { /* Why 32512? I dont know! */
1106 statusbar(_("Could not invoke \"ispell\""));
1107 exit_spell(temp, foo);
1108 return 0;
1109 }
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001110/* initscr(); */
1111 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001112
1113 free_filestruct(fileage);
1114 global_init();
1115 open_file(temp, 0, 1);
1116 edit_update(fileage);
1117 set_modified();
1118 exit_spell(temp, foo);
1119 statusbar(_("Finished checking spelling"));
1120 return 1;
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001121#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001122}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001123
1124int do_exit(void)
1125{
1126 int i;
1127
1128 if (!ISSET(MODIFIED))
1129 finish(0);
1130
Chris Allegretta30885552000-07-14 01:20:12 +00001131 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001132 i = 1;
1133 } else {
1134 i =
1135 do_yesno(0, 0,
1136 _
1137 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1138 }
1139
1140#ifdef DEBUG
1141 dump_buffer(fileage);
1142#endif
1143
1144 if (i == 1) {
1145 if (do_writeout(1) > 0)
1146 finish(0);
1147 } else if (i == 0)
1148 finish(0);
1149 else
1150 statusbar(_("Cancelled"));
1151
1152 display_main_list();
1153 return 1;
1154}
1155
1156#ifndef NANO_SMALL
1157#ifdef NCURSES_MOUSE_VERSION
1158void do_mouse(void)
1159{
1160 MEVENT mevent;
1161
1162 if (getmouse(&mevent) == ERR)
1163 return;
1164
1165 /* If mouse not in edit window, return (add help selection later). */
1166 if (!wenclose(edit, mevent.y, mevent.x))
1167 return;
1168
1169 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1170 mevent.y -= 2;
1171
1172 /* Selecting where the cursor is sets the mark.
1173 * Selecting beyond the line length with the cursor at the end of the
1174 * line sets the mark as well.
1175 */
1176 if ((mevent.y == current_y) &&
1177 ((mevent.x == current_x) || (current_x == strlen(current->data)
1178 && (mevent.x >
1179 strlen(current->data))))) {
1180 if (ISSET(VIEW_MODE)) {
1181 print_view_warning();
1182 return;
1183 }
1184 do_mark();
1185 } else if (mevent.y > current_y) {
1186 while (mevent.y > current_y) {
1187 if (current->next != NULL)
1188 current = current->next;
1189 else
1190 break;
1191 current_y++;
1192 }
1193 } else if (mevent.y < current_y) {
1194 while (mevent.y < current_y) {
1195 if (current->prev != NULL)
1196 current = current->prev;
1197 else
1198 break;
1199 current_y--;
1200 }
1201 }
1202 current_x = mevent.x;
1203 if (current_x > strlen(current->data))
1204 current_x = strlen(current->data);
1205
1206 update_cursor();
1207 edit_refresh();
1208
1209}
1210#endif
1211#endif
1212
1213/* Handler for SIGHUP */
1214RETSIGTYPE handle_hup(int signal)
1215{
1216 write_file("nano.save", 0);
1217 finish(1);
1218}
1219
1220
1221void handle_sigwinch(int s)
1222{
1223#ifndef NANO_SMALL
1224 char *tty = NULL;
1225 int fd = 0;
1226 int result = 0;
1227 int i = 0;
1228 struct winsize win;
1229
1230 tty = ttyname(0);
1231 if (!tty)
1232 return;
1233 fd = open(tty, O_RDWR);
1234 if (fd == -1)
1235 return;
1236 result = ioctl(fd, TIOCGWINSZ, &win);
1237 if (result == -1)
1238 return;
1239
1240
1241 COLS = win.ws_col;
1242 LINES = win.ws_row;
1243
1244 center_x = COLS / 2;
1245 center_y = LINES / 2;
1246 editwinrows = LINES - 5 + no_help();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001247 fill = COLS - 8;
1248
1249 free(hblank);
1250 hblank = nmalloc(COLS + 1);
1251
1252 for (i = 0; i <= COLS - 1; i++)
1253 hblank[i] = ' ';
1254 hblank[i] = 0;
1255
1256#ifdef HAVE_NCURSES_H
1257 resizeterm(LINES, COLS);
1258#ifdef HAVE_WRESIZE
1259 if (wresize(topwin, 2, COLS) == ERR)
1260 die(_("Cannot resize top win"));
1261 if (mvwin(topwin, 0, 0) == ERR)
1262 die(_("Cannot move top win"));
1263 if (wresize(edit, editwinrows, COLS) == ERR)
1264 die(_("Cannot resize edit win"));
1265 if (mvwin(edit, 2, 0) == ERR)
1266 die(_("Cannot move edit win"));
1267 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1268 die(_("Cannot resize bottom win"));
1269 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1270 die(_("Cannot move bottom win"));
1271#endif /* HAVE_WRESIZE */
1272#endif /* HAVE_NCURSES_H */
1273
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001274 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001275
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001276 if (current_y > editwinrows - 1) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001277 edit_update(editbot);
1278 }
1279 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001280
1281 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001282 refresh();
Chris Allegretta97accc62000-06-19 05:45:52 +00001283 titlebar();
1284 edit_refresh();
1285 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001286 total_refresh();
1287#endif
1288}
1289
1290int do_tab(void)
1291{
1292 do_char('\t');
1293 return 1;
1294}
1295
1296#ifndef NANO_SMALL
1297int empty_line(const char *data)
1298{
1299 while (*data) {
1300 if (!isspace(*data))
1301 return 0;
1302
1303 data++;
1304 }
1305
1306 return 1;
1307}
1308
1309int no_spaces(const char *data)
1310{
1311 while (*data) {
1312 if (isspace(*data))
1313 return 0;
1314
1315 data++;
1316 }
1317
1318 return 1;
1319}
1320
1321void justify_format(char *data)
1322{
1323 int i = 0;
1324 int len = strlen(data);
1325
1326 /* Skip first character regardless and leading whitespace. */
1327 for (i = 1; i < len; i++) {
1328 if (!isspace(data[i]))
1329 break;
1330 }
1331
1332 i++; /* (i) is now at least 2. */
1333
1334 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
1335 for (; i < len; i++) {
1336 if (isspace(data[i]) && isspace(data[i - 1])
1337 && (data[i - 2] != '.')) {
1338 memmove(data + i, data + i + 1, len - i);
1339 len--;
1340 i--;
1341 }
1342 }
1343}
1344#endif
1345
1346int do_justify(void)
1347{
1348#ifndef NANO_SMALL
1349 int slen = 0; /* length of combined lines on one line. */
1350 int initial_y;
1351 filestruct *initial = NULL;
1352
1353 if (empty_line(current->data)) {
1354 /* Justify starting at first non-empty line. */
1355 do {
1356 if (!current->next)
1357 return 1;
1358
1359 current = current->next;
1360 current_y++;
1361 }
1362 while (empty_line(current->data));
1363 } else {
1364 /* Search back for the beginning of the paragraph, where
1365 * Paragraph is 1) A line with leading whitespace
1366 * or 2) A line following an empty line.
1367 */
1368 while (current->prev != NULL) {
1369 if (isspace(current->data[0]) || !current->data[0])
1370 break;
1371
1372 current = current->prev;
1373 current_y--;
1374 }
1375
1376 /* First line with leading whitespace may be empty. */
1377 if (empty_line(current->data)) {
1378 if (current->next) {
1379 current = current->next;
1380 current_y++;
1381 } else
1382 return 1;
1383 }
1384 }
1385 initial = current;
1386 initial_y = current_y;
1387
1388 set_modified();
1389 /* Put the whole paragraph into one big line. */
1390 while (current->next && !isspace(current->next->data[0])
1391 && current->next->data[0]) {
1392 filestruct *tmpnode = current->next;
1393 int len = strlen(current->data);
1394 int len2 = strlen(current->next->data);
1395
1396 /* length of both strings plus space between strings and ending \0. */
1397 current->data = nrealloc(current->data, len + len2 + 2);
1398 current->data[len++] = ' ';
1399 current->data[len] = '\0';
1400
1401 strncat(current->data, current->next->data, len2);
1402
1403 unlink_node(tmpnode);
1404 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001405 }
1406
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001407 totsize -= strlen(current->data);
1408
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001409 justify_format(current->data);
1410
1411 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001412 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001413
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001414 if((strlenpt(current->data) > (fill))
1415 && !no_spaces(current->data)) {
1416 do {
1417 int i = 0;
1418 int len2 = 0;
1419 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001420
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001421 /* Start at fill , unless line isn't that long (but it
1422 * appears at least fill long with tabs.
1423 */
1424 if (slen > fill)
1425 i = fill;
1426 else
1427 i = slen;
1428 for (; i > 0; i--) {
1429 if (isspace(current->data[i]) &&
1430 ((strlenpt(current->data) - strlen(current->data +i)) <=
1431 fill)) break;
1432 }
1433 if (!i)
1434 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001435
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001436 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001437
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001438 len2 = strlen(current->data + i + 1);
1439 tmpline->data = nmalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001440
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001441 /* Skip the white space in current. */
1442 memcpy(tmpline->data, current->data + i + 1, len2);
1443 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001444
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001445 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001446
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001447 tmpline->prev = current;
1448 tmpline->next = current->next;
1449 if (current->next != NULL)
1450 current->next->prev = tmpline;
1451
1452 current->next = tmpline;
1453 current = tmpline;
1454 slen -= i + 1;
1455 current_y++;
1456 } while ((strlenpt(current->data) > (fill))
1457 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001458 }
1459
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001460 if (current->next)
1461 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00001462 else
1463 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001464 current_x = 0;
1465 placewewant = 0;
1466
Adam Rogoyski09f97962000-06-20 02:50:33 +00001467 renumber(initial);
1468 totlines = filebot->lineno;
1469
1470 werase(edit);
1471
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001472 if ((current_y < 0) || (current_y >= editwinrows - 1)
1473 || (initial_y <= 0)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001474 edit_update(current);
1475 center_cursor();
1476 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001477 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001478 }
1479
Adam Rogoyski09f97962000-06-20 02:50:33 +00001480 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001481 statusbar("Justify Complete");
1482 return 1;
1483#else
1484 nano_small_msg();
1485 return 1;
1486#endif
1487}
1488
1489
1490void help_init(void)
1491{
1492 int i, sofar = 0;
1493 long allocsize = 1; /* How much space we're gonna need for the help text */
1494 char buf[BUFSIZ];
1495
1496 /* Compute the space needed for the shortcut lists - we add 15 to
1497 have room for the shortcut abbrev and its possible alternate keys */
1498 for (i = 0; i < MAIN_LIST_LEN; i++)
1499 if (main_list[i].help != NULL)
1500 allocsize += strlen(main_list[i].help) + 15;
1501
1502 allocsize += strlen(help_text_init);
1503
1504 if (help_text != NULL)
1505 free(help_text);
1506
1507 /* Allocate space for the help text */
1508 help_text = nmalloc(allocsize);
1509
1510 /* Now add the text we want */
1511 strcpy(help_text, help_text_init);
1512
1513 /* Now add our shortcut info */
1514 for (i = 0; i < MAIN_LIST_LEN; i++) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001515 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001516
1517 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00001518 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001519 main_list[i].misc1 - KEY_F0);
1520 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001521 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001522
1523 if (main_list[i].altval > 0)
Robert Siemborski6af14312000-07-01 21:34:26 +00001524 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(@%c) ",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001525 main_list[i].altval - 32);
1526 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001527 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001528
1529 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00001530 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001531
1532 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00001533 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001534 }
1535
1536}
1537
1538int main(int argc, char *argv[])
1539{
1540 int optchr;
1541 int kbinput; /* Input from keyboard */
1542 long startline = 0; /* Line to try and start at */
1543 struct sigaction act; /* For our lovely signals */
1544 int keyhandled = 0; /* Have we handled the keystroke yet? */
1545 int tmpkey = 0, i;
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001546#ifdef HAVE_TABSIZE
1547 int usrtabsize = 0; /* User defined tab size */
1548#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001549 char *argv0;
1550 struct termios term;
1551
1552#ifdef HAVE_GETOPT_LONG
1553 int option_index = 0;
1554 struct option long_options[] = {
Chris Allegretta47805612000-07-07 02:35:34 +00001555#ifdef _POSIX_VERSION
Chris Allegretta9fc8d432000-07-07 01:49:52 +00001556 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00001557#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001558 {"version", 0, 0, 'V'},
1559 {"const", 0, 0, 'c'},
1560 {"suspend", 0, 0, 'z'},
1561 {"nowrap", 0, 0, 'w'},
1562 {"nohelp", 0, 0, 'x'},
1563 {"help", 0, 0, 'h'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00001564#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00001565 {"cut", 0, 0, 'k'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00001566#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001567 {"autoindent", 0, 0, 'i'},
1568 {"tempfile", 0, 0, 't'},
1569 {"speller", 1, 0, 's'},
1570 {"fill", 1, 0, 'r'},
1571 {"mouse", 0, 0, 'm'},
1572 {"pico", 0, 0, 'p'},
1573 {"nofollow", 0, 0, 'l'},
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001574#ifdef HAVE_TABSIZE
1575 {"tabsize", 0, 0, 'T'},
1576#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001577 {0, 0, 0, 0}
1578 };
1579#endif
1580
1581 /* Flag inits... */
1582 SET(FOLLOW_SYMLINKS);
1583
1584#ifndef NANO_SMALL
1585 setlocale(LC_ALL, "");
1586 bindtextdomain(PACKAGE, LOCALEDIR);
1587 textdomain(PACKAGE);
1588#endif
1589
1590#ifdef HAVE_GETOPT_LONG
Chris Allegretta627de192000-07-12 02:09:17 +00001591 while ((optchr = getopt_long(argc, argv, "?T:RVchiklmpr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001592 long_options, &option_index)) != EOF) {
1593#else
Chris Allegretta627de192000-07-12 02:09:17 +00001594 while ((optchr = getopt(argc, argv, "h?T:RVciklmpr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001595#endif
1596
1597 switch (optchr) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001598#ifdef HAVE_TABSIZE
1599 case 'T':
1600 usrtabsize = atoi(optarg);
1601 if (usrtabsize <= 0) {
1602 usage(); /* To stop bogus data for tab width */
1603 finish(1);
1604 }
1605 break;
1606#else
1607 case 'T':
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001608 usage(); /* Oops! You dont really have that option */
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001609 finish(1);
1610#endif
Chris Allegretta47805612000-07-07 02:35:34 +00001611#ifdef _POSIX_VERSION
Chris Allegretta9fc8d432000-07-07 01:49:52 +00001612 case 'R':
1613 SET(USE_REGEXP);
1614 break;
Chris Allegretta47805612000-07-07 02:35:34 +00001615#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001616 case 'V':
1617 version();
1618 exit(0);
1619 case 'c':
1620 SET(CONSTUPDATE);
1621 break;
1622 case 'h':
1623 case '?':
1624 usage();
1625 exit(0);
1626 case 'i':
1627 SET(AUTOINDENT);
1628 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00001629#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00001630 case 'k':
1631 SET(CUT_TO_END);
1632 break;
Chris Allegretta18bd0292000-07-28 01:18:10 +00001633#else
1634 case 'k':
1635 usage(); /* Oops! You dont really have that option */
1636 finish(1);
Chris Allegrettad19e9912000-07-12 18:14:51 +00001637#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001638 case 'l':
1639 UNSET(FOLLOW_SYMLINKS);
1640 break;
1641 case 'm':
1642 SET(USE_MOUSE);
1643 break;
1644 case 'p':
1645 SET(PICO_MSGS);
1646 break;
1647 case 'r':
1648 fill = atoi(optarg);
1649 if (fill <= 0) {
1650 usage(); /* To stop bogus data (like a string) */
1651 finish(1);
1652 }
1653 break;
1654 case 's':
1655 alt_speller = nmalloc(strlen(optarg) + 1);
1656 strcpy(alt_speller, optarg);
1657 break;
1658 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00001659 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001660 break;
1661 case 'v':
1662 SET(VIEW_MODE);
1663 break;
1664 case 'w':
1665 SET(NO_WRAP);
1666 break;
1667 case 'x':
1668 SET(NO_HELP);
1669 break;
1670 case 'z':
1671 SET(SUSPEND);
1672 break;
1673 default:
1674 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001675 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001676 }
1677
1678 }
1679
1680 argv0 = strrchr(argv[0], '/');
1681 if ((argv0 && strstr(argv0, "pico"))
1682 || (!argv0 && strstr(argv[0], "pico")))
1683 SET(PICO_MSGS);
1684
1685 filename = nmalloc(PATH_MAX);
1686 strcpy(filename, "");
1687
1688 /* See if there's a non-option in argv (first non-option is the
1689 filename, if +LINE is not given) */
1690 if (argc == 1 || argc <= optind)
1691 strcpy(filename, "");
1692 else {
1693 /* Look for the +line flag... */
1694 if (argv[optind][0] == '+') {
1695 startline = atoi(&argv[optind][1]);
1696 optind++;
1697 if (argc == 1 || argc <= optind)
1698 strcpy(filename, "");
1699 else
1700 strncpy(filename, argv[optind], 132);
1701 } else
1702 strncpy(filename, argv[optind], 132);
1703
1704 }
1705
1706
1707 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001708 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001709
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001710 term = oldterm;
1711 term.c_cc[VINTR] = _POSIX_VDISABLE;
1712 term.c_cc[VQUIT] = _POSIX_VDISABLE;
1713 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001714 tcsetattr(0, TCSANOW, &term);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001715
1716 /* now ncurses init stuff... */
1717 initscr();
1718 savetty();
1719 nonl();
1720 cbreak();
1721 noecho();
1722 timeout(0);
1723
1724 /* Set up some global variables */
1725 global_init();
1726 shortcut_init();
1727 init_help_msg();
1728 help_init();
1729
1730 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001731 memset(&act, 0, sizeof(struct sigaction));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001732 act.sa_handler = SIG_IGN;
1733 sigaction(SIGINT, &act, NULL);
1734 sigaction(SIGQUIT, &act, NULL);
1735
1736 if (!ISSET(SUSPEND))
1737 sigaction(SIGTSTP, &act, NULL);
1738
1739 /* Trap SIGHUP cuz we want to write the file out. */
1740 act.sa_handler = handle_hup;
1741 sigaction(SIGHUP, &act, NULL);
1742
1743 act.sa_handler = handle_sigwinch;
1744 sigaction(SIGWINCH, &act, NULL);
1745
1746#ifdef DEBUG
1747 fprintf(stderr, _("Main: set up windows\n"));
1748#endif
1749
1750 /* Setup up the main text window */
1751 edit = newwin(editwinrows, COLS, 2, 0);
1752 keypad(edit, TRUE);
1753
1754#ifndef NANO_SMALL
1755#ifdef NCURSES_MOUSE_VERSION
1756 if (ISSET(USE_MOUSE)) {
1757 mousemask(BUTTON1_RELEASED, NULL);
1758 mouseinterval(50);
1759 }
1760#endif
1761#endif
1762
1763 /* And the other windows */
1764 topwin = newwin(2, COLS, 0, 0);
1765 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
1766 keypad(bottomwin, TRUE);
1767
1768#ifdef DEBUG
1769 fprintf(stderr, _("Main: bottom win\n"));
1770#endif
1771 /* Set up up bottom of window */
1772 display_main_list();
1773
1774#ifdef DEBUG
1775 fprintf(stderr, _("Main: open file\n"));
1776#endif
1777
1778 titlebar();
1779 if (argc == 1)
1780 new_file();
1781 else
1782 open_file(filename, 0, 0);
1783
1784 if (startline > 0)
1785 do_gotoline(startline);
1786 else
1787 edit_update(fileage);
1788
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001789#ifdef HAVE_TABSIZE
1790 if (usrtabsize > 0)
1791 TABSIZE = usrtabsize;
1792#endif
1793
Robert Siemborski6967eec2000-07-08 14:23:32 +00001794 edit_refresh();
1795 reset_cursor();
1796
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001797 while (1) {
1798 kbinput = wgetch(edit);
1799 if (kbinput == 27) { /* Grab Alt-key stuff first */
1800 switch (kbinput = wgetch(edit)) {
1801 case 91:
1802
1803 switch (kbinput = wgetch(edit)) {
1804 case 'A':
1805 kbinput = KEY_UP;
1806 break;
1807 case 'B':
1808 kbinput = KEY_DOWN;
1809 break;
1810 case 'C':
1811 kbinput = KEY_RIGHT;
1812 break;
1813 case 'D':
1814 kbinput = KEY_LEFT;
1815 break;
1816 case 'H':
1817 kbinput = KEY_HOME;
1818 break;
1819 case 'F':
1820 kbinput = KEY_END;
1821 break;
1822 case 49: /* X window F-keys */
1823 tmpkey = wgetch(edit);
1824 kbinput = KEY_F(tmpkey) - 48;
1825 wgetch(edit); /* Junk character */
1826 break;
1827 case 53: /* page up */
1828 kbinput = KEY_PPAGE;
1829 if ((kbinput = wgetch(edit)) == 126)
1830 kbinput = KEY_PPAGE; /* Ignore extra tilde */
1831 else { /* I guess this could happen ;-) */
1832 ungetch(kbinput);
1833 continue;
1834 }
1835 break;
1836 case 54: /* page down */
1837 kbinput = KEY_NPAGE;
1838 if ((kbinput = wgetch(edit)) == 126)
1839 kbinput = KEY_NPAGE; /* Same thing here */
1840 else {
1841 ungetch(kbinput);
1842 continue;
1843 }
1844 break;
1845
1846 default:
1847#ifdef DEBUG
1848 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
1849 kbinput, kbinput);
1850#endif
1851 break;
1852 }
1853 break;
1854 default:
1855
1856 /* Check for the altkey defs.... */
1857 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
1858 if (kbinput == main_list[i].altval ||
1859 kbinput == main_list[i].altval - 32) {
1860 kbinput = main_list[i].val;
1861 break;
1862 }
1863#ifdef DEBUG
1864 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
1865 kbinput);
1866#endif
1867 break;
1868 }
1869 }
1870 /* Look through the main shortcut list to see if we've hit a
1871 shortcut key */
1872 for (i = 0; i < MAIN_LIST_LEN; i++) {
1873 if (kbinput == main_list[i].val ||
1874 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
1875 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
1876 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
1877 print_view_warning();
1878 else
1879 main_list[i].func();
1880 keyhandled = 1;
1881 }
1882 }
1883 /* Last gasp, stuff that's not in the main lists */
1884 if (!keyhandled)
1885 switch (kbinput) {
1886#ifndef NANO_SMALL
1887#ifdef NCURSES_MOUSE_VERSION
1888 case KEY_MOUSE:
1889 do_mouse();
1890 break;
1891#endif
1892#endif
1893 case 0: /* Erg */
1894 do_next_word();
1895 break;
1896 case 331: /* Stuff that we don't want to do squat */
1897 case -1:
1898 case 410: /* Must ignore this, it gets sent when we resize */
1899 break;
1900 default:
1901#ifdef DEBUG
1902 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
1903#endif
1904 /* We no longer stop unhandled sequences so that people with
1905 odd character sets can type... */
1906
1907 if (ISSET(VIEW_MODE)) {
1908 print_view_warning();
1909 break;
1910 }
1911 do_char(kbinput);
1912 }
1913 if (ISSET(CONSTUPDATE))
1914 do_cursorpos();
1915
1916 reset_cursor();
1917 wrefresh(edit);
1918 keyhandled = 0;
1919 }
1920
1921 getchar();
1922 finish(0);
1923
1924}