blob: a1e25a95d0b2bf51f8fd87757d2ed166b424392a [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * nano.c *
4 * *
5 * Copyright (C) 1999 Chris Allegretta *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 1, or (at your option) *
9 * any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <stdarg.h>
25#include <signal.h>
26#include <unistd.h>
27#include <string.h>
28#include <fcntl.h>
29#include <sys/stat.h>
30#include <sys/ioctl.h>
31#include <sys/param.h>
32#include <errno.h>
33#include <ctype.h>
34#include <locale.h>
35#include <limits.h>
Adam Rogoyski77f36de2000-06-07 03:56:54 +000036#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000037
38#include "config.h"
39#include "proto.h"
40#include "nano.h"
41
42#ifndef NANO_SMALL
43#include <libintl.h>
44#define _(string) gettext(string)
45#else
46#define _(string) (string)
47#endif
48
49#ifdef HAVE_TERMIOS_H
50#include <termios.h>
51#endif
52
53#ifdef HAVE_TERMIO_H
54#include <termio.h>
55#endif
56
57#ifdef HAVE_GETOPT_H
58#include <getopt.h>
59#endif
60
61/* Former globals, now static */
Chris Allegretta8f6c0692000-07-19 01:16:18 +000062char *last_search = "\0"; /* Last string we searched for */
63char *last_replace = "\0"; /* Last replacement string */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000064int fill = 0; /* Fill - where to wrap lines, basically */
65static char *alt_speller; /* Alternative spell command */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000066struct termios oldterm; /* The user's original term settings */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000067static char *help_text_init = "";
68 /* Initial message, not including shortcuts */
69
70/* What we do when we're all set to exit */
71RETSIGTYPE finish(int sigage)
72{
73 if (!ISSET(NO_HELP)) {
74 mvwaddstr(bottomwin, 1, 0, hblank);
75 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000076 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000077 mvwaddstr(bottomwin, 0, 0, hblank);
78
79 wrefresh(bottomwin);
80 endwin();
81
82 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +000083 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000084
85 exit(sigage);
86}
87
88/* Die (gracefully?) */
89void die(char *msg, ...)
90{
91 va_list ap;
92
93 va_start(ap, msg);
94 vfprintf(stderr, msg, ap);
95 va_end(ap);
96
97 /* if we can't save we have REAL bad problems,
Robert Siemborskifcf32bf2000-07-17 03:04:54 +000098 * but we might as well TRY. */
99 if(filename[0] == '\0') {
100 write_file("nano.save", 0);
101 } else {
102 char buf[BUFSIZ];
103 strncpy(buf,filename,BUFSIZ);
104 strncat(buf,".save",BUFSIZ - strlen(buf));
105 write_file(buf, 0);
106 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000107 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000108 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000109
110 clear();
111 refresh();
112 resetty();
113 endwin();
114
115 fprintf(stderr, msg);
116 fprintf(stderr, _("\nBuffer written to 'nano.save'\n"));
117
118 exit(1); /* We have a problem: exit w/ errorlevel(1) */
119}
120
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000121void print_view_warning(void)
122{
123 statusbar(_("Key illegal in VIEW mode"));
124}
125
126/* Initialize global variables - no better way for now */
127void global_init(void)
128{
129 int i;
130
131 center_x = COLS / 2;
132 center_y = LINES / 2;
133 current_x = 0;
134 current_y = 0;
135 editwinrows = LINES - 5 + no_help();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000136 fileage = NULL;
137 cutbuffer = NULL;
138 current = NULL;
139 edittop = NULL;
140 editbot = NULL;
141 totlines = 0;
142 placewewant = 0;
143 if (!fill)
144 fill = COLS - 8;
145 hblank = nmalloc(COLS + 1);
146
147 /* Thanks BG for this bit... */
148 for (i = 0; i <= COLS - 1; i++)
149 hblank[i] = ' ';
150 hblank[i] = 0;
151 last_search = nmalloc(132);
152 last_replace = nmalloc(132);
153 answer = nmalloc(132);
154
155}
156
157void init_help_msg(void)
158{
159
160#ifndef NANO_SMALL
161
162 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000163 _(" nano help text\n\n "
164 "The nano editor is designed to emulate the functionality and "
165 "ease-of-use of the UW Pico text editor. There are four main "
166 "sections of the editor: The top line shows the program "
167 "version, the current filename being edited, and whether "
168 "or not the file has been modified. Next is the main editor "
169 "window showing the file being edited. The status line is "
170 "the third line from the bottom and shows important messages. "
171 "The bottom two lines show the most commonly used shortcuts "
172 "in the editor.\n\n "
173 "The notation for shortcuts is as follows: Control-key "
174 "sequences are notated with a caret (^) symbol. Alt-key "
175 "sequences are notated with an at (@) symbol. The following "
176 "keystrokes are available in the main editor window. "
177 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000178#endif
179
180}
181
182/* Make a copy of a node to a pointer (space will be malloc()ed) */
183filestruct *copy_node(filestruct * src)
184{
185 filestruct *dst;
186
187 dst = nmalloc(sizeof(filestruct));
188 dst->data = nmalloc(strlen(src->data) + 1);
189
190 dst->next = src->next;
191 dst->prev = src->prev;
192
193 strcpy(dst->data, src->data);
194 dst->lineno = src->lineno;
195
196 return dst;
197}
198
199/* Unlink a node from the rest of the struct */
200void unlink_node(filestruct * fileptr)
201{
202 if (fileptr->prev != NULL)
203 fileptr->prev->next = fileptr->next;
204
205 if (fileptr->next != NULL)
206 fileptr->next->prev = fileptr->prev;
207}
208
209void delete_node(filestruct * fileptr)
210{
211 if (fileptr->data != NULL)
212 free(fileptr->data);
213 free(fileptr);
214}
215
216/* Okay, now let's duplicate a whole struct! */
217filestruct *copy_filestruct(filestruct * src)
218{
219 filestruct *dst, *tmp, *head, *prev;
220
221 head = copy_node(src);
222 dst = head; /* Else we barf on copying just one line */
223 head->prev = NULL;
224 tmp = src->next;
225 prev = head;
226
227 while (tmp != NULL) {
228 dst = copy_node(tmp);
229 dst->prev = prev;
230 prev->next = dst;
231
232 prev = dst;
233 tmp = tmp->next;
234 }
235
236 dst->next = NULL;
237 return head;
238}
239
240/* Free() a single node */
241int free_node(filestruct * src)
242{
243 if (src == NULL)
244 return 0;
245
246 if (src->next != NULL)
247 free(src->data);
248 free(src);
249 return 1;
250}
251
252int free_filestruct(filestruct * src)
253{
254 filestruct *fileptr = src;
255
256 if (src == NULL)
257 return 0;
258
259 while (fileptr->next != NULL) {
260 fileptr = fileptr->next;
261 free_node(fileptr->prev);
262
263#ifdef DEBUG
264 fprintf(stderr, _("free_node(): free'd a node, YAY!\n"));
265#endif
266 }
267 free_node(fileptr);
268#ifdef DEBUG
269 fprintf(stderr, _("free_node(): free'd last node.\n"));
270#endif
271
272 return 1;
273}
274
275int renumber_all(void)
276{
277 filestruct *temp;
278 long i = 1;
279
280 for (temp = fileage; temp != NULL; temp = temp->next) {
281 temp->lineno = i++;
282 }
283
284 return 0;
285}
286
287int renumber(filestruct * fileptr)
288{
289 filestruct *temp;
290
291 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
292 renumber_all();
293 return 0;
294 }
295 for (temp = fileptr; temp != NULL; temp = temp->next) {
296 temp->lineno = temp->prev->lineno + 1;
297 }
298
299 return 0;
300}
301
302/* Fix the memory allocation for a string */
303void align(char **strp)
304{
305 /* There was a serious bug here: the new address was never
306 stored anywhere... */
307
308 *strp = nrealloc(*strp, strlen(*strp) + 1);
309}
310
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000311/* Null a string at a certain index and align it */
312void null_at(char *data, int index)
313{
314 data[index] = 0;
315 align(&data);
316}
317
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000318void usage(void)
319{
320#ifdef HAVE_GETOPT_LONG
321 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
322 printf(_("Option Long option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000323 printf(_
324 (" -T --tabsize=[num] Set width of a tab to num\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000325#ifdef _POSIX_VERSION
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000326 printf(_
327 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000328#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000329 printf
330 (_
331 (" -V --version Print version information and exit\n"));
332 printf(_
333 (" -c --const Constantly show cursor position\n"));
334 printf(_
335 (" -h --help Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000336#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000337 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000338 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000339#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000340 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000341 (" -i --autoindent Automatically indent new lines\n"));
342 printf(_
343 (" -l --nofollow Don't follow symbolic links, overwrite.\n"));
344#ifndef NANO_SMALL
345#ifdef NCURSES_MOUSE_VERSION
346 printf(_(" -m --mouse Enable mouse\n"));
347#endif
348#endif
349 printf
350 (_
351 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
352 printf(_
353 (" -p --pico Make bottom 2 lines more Pico-like\n"));
354 printf(_
355 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
356 printf(_
357 (" -t --tempfile Auto save on exit, don't prompt\n"));
358 printf(_
359 (" -v --view View (read only) mode\n"));
360 printf(_
361 (" -w --nowrap Don't wrap long lines\n"));
362 printf(_
363 (" -x --nohelp Don't show help window\n"));
364 printf(_
365 (" -z --suspend Enable suspend\n"));
366 printf(_
367 (" +LINE Start at line number LINE\n"));
368#else
369 printf(_("Usage: nano [option] +LINE <file>\n\n"));
370 printf(_("Option Meaning\n"));
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000371 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000372 printf(_(" -R Use regular expressions for search\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000373 printf(_(" -V Print version information and exit\n"));
374 printf(_(" -c Constantly show cursor position\n"));
375 printf(_(" -h Show this message\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000376#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +0000377 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000378#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000379 printf(_(" -i Automatically indent new lines\n"));
380 printf(_
381 (" -l Don't follow symbolic links, overwrite.\n"));
382#ifndef NANO_SMALL
383#ifdef NCURSES_MOUSE_VERSION
384 printf(_(" -m Enable mouse\n"));
385#endif
386#endif
387 printf(_
388 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
389 printf(_(" -s [prog] Enable alternate speller\n"));
390 printf(_(" -p Make bottom 2 lines more Pico-like\n"));
391 printf(_(" -t Auto save on exit, don't prompt\n"));
392 printf(_(" -v View (read only) mode\n"));
393 printf(_(" -w Don't wrap long lines\n"));
394 printf(_(" -x Don't show help window\n"));
395 printf(_(" -z Enable suspend\n"));
396 printf(_(" +LINE Start at line number LINE\n"));
397#endif
398 exit(0);
399}
400
401void version(void)
402{
403 printf(_(" nano version %s by Chris Allegretta (compiled %s, %s)\n"),
404 VERSION, __TIME__, __DATE__);
405 printf(_(" Email: nano@asty.org Web: http://www.asty.org/nano\n"));
406}
407
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000408filestruct *make_new_node(filestruct * prevnode)
409{
410 filestruct *newnode;
411
412 newnode = nmalloc(sizeof(filestruct));
413 newnode->data = NULL;
414
415 newnode->prev = prevnode;
416 newnode->next = NULL;
417
418 if (prevnode != NULL)
419 newnode->lineno = prevnode->lineno + 1;
420
421 return newnode;
422}
423
Chris Allegretta7975ed82000-07-28 00:58:35 +0000424/* Splice a node into an existing filestruct */
425void splice_node(filestruct *begin, filestruct *new, filestruct *end)
426{
427 new->next = end;
428 new->prev = begin;
429 begin->next = new;
430 if (end != NULL)
431 end->prev = new;
432}
433
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000434int do_mark()
435{
436#ifdef NANO_SMALL
437 nano_small_msg();
438#else
439 if (!ISSET(MARK_ISSET)) {
440 statusbar(_("Mark Set"));
441 SET(MARK_ISSET);
442 mark_beginbuf = current;
443 mark_beginx = current_x;
444 } else {
445 statusbar(_("Mark UNset"));
446 UNSET(MARK_ISSET);
447 mark_beginbuf = NULL;
448 mark_beginx = 0;
449
450 edit_refresh();
451 }
452#endif
453 return 1;
454}
455
456int no_help(void)
457{
458 if ISSET
459 (NO_HELP)
460 return 2;
461 else
462 return 0;
463}
464
465void nano_small_msg(void)
466{
467 statusbar("Sorry, this function not available with nano-tiny option");
468}
469
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000470/* The user typed a printable character; add it to the edit buffer */
471void do_char(char ch)
472{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000473 /* magic-line: when a character is inserted on the current magic line,
474 * it means we need a new one! */
475 if(filebot == current && current->data[0] == '\0') {
476 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000477 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000478 }
479
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000480 /* More dangerousness fun =) */
481 current->data = nrealloc(current->data, strlen(current->data) + 2);
482 memmove(&current->data[current_x + 1],
483 &current->data[current_x],
484 strlen(current->data) - current_x + 1);
485 current->data[current_x] = ch;
486 do_right();
487
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000488 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000489 check_wrap(current, ch);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000490 set_modified();
491 check_statblank();
492 UNSET(KEEP_CUTBUFFER);
493 totsize++;
494
495}
496
497/* Someone hits return *gasp!* */
498int do_enter(filestruct * inptr)
499{
500 filestruct *new;
501 char *tmp, *spc;
502 int extra = 0;
503
504 new = make_new_node(inptr);
505 tmp = &current->data[current_x];
506 current_x = 0;
507
508 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
509 if (ISSET(AUTOINDENT)) {
510 spc = current->data;
511 if (spc) {
512 while ((*spc == ' ') || (*spc == '\t')) {
513 extra++;
514 spc++;
515 current_x++;
516 }
517 new->data = nmalloc(strlen(tmp) + extra + 1);
518 strncpy(new->data, current->data, extra);
519 strcpy(&new->data[extra], tmp);
520 }
521 } else {
522 new->data = nmalloc(strlen(tmp) + 1);
523 strcpy(new->data, tmp);
524 }
525 *tmp = 0;
526
Chris Allegrettada721be2000-07-31 01:26:42 +0000527 if (inptr->next == NULL) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000528 filebot = new;
529 editbot = new;
530 }
Chris Allegretta7975ed82000-07-28 00:58:35 +0000531 splice_node(inptr, new, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000532
533 totsize++;
534 renumber(current);
535 current = new;
536 align(&current->data);
537
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000538 /* The logic here is as follows:
539 * -> If we are at the bottom of the buffer, we want to recenter
540 * (read: rebuild) the screen and forcably move the cursor.
541 * -> otherwise, we want simply to redraw the screen and update
542 * where we think the cursor is.
543 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000544 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000545 edit_update(current, CENTER);
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000546 reset_cursor();
547 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000548 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000549 edit_refresh();
550 update_cursor();
551 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000552
553 totlines++;
554 set_modified();
555
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000556 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000557 return 1;
558}
559
560int do_enter_void(void)
561{
562 return do_enter(current);
563}
564
565void do_next_word(void)
566{
567 filestruct *fileptr;
568 int i;
569
570 if (current == NULL)
571 return;
572
573 i = current_x;
574 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
575 if (fileptr == current) {
576 while (isalnum((int) fileptr->data[i])
577 && fileptr->data[i] != 0)
578 i++;
579
580 if (fileptr->data[i] == 0) {
581 i = 0;
582 continue;
583 }
584 }
585 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
586 i++;
587
588 if (fileptr->data[i] != 0)
589 break;
590
591 i = 0;
592 }
593 if (fileptr == NULL)
594 current = filebot;
595 else
596 current = fileptr;
597
598 current_x = i;
599 placewewant = xplustabs();
600 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000601 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000602
603}
604
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000605void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000606{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000607 int i = 0; /* Index into ->data for line. */
608 int i_tabs = 0; /* Screen position of ->data[i]. */
609 int last_word_end = -1; /* Location of end of last word found. */
610 int current_word_start = -1; /* Location of start of current word. */
611 int current_word_start_t = -1; /* Location of start of current word screen position. */
612 int current_word_end = -1; /* Location of end of current word */
613 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000614 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000615
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000616 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000617 int right = 0;
618 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000619
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000620 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000621
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000622 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000623 if (!isspace(inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000624 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000625
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000626 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000627 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000628
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000629 while (!isspace(inptr->data[i]) && inptr->data[i]) {
630 i++;
631 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000632 if (inptr->data[i] < 32)
633 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000634 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000635
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000636 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000637 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000638 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000639 } else {
640 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000641 current_word_end_t = i_tabs - 1;
642 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000643 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000644
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000645 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000646 if (i_tabs % tabsize != 0);
647 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000648 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000649
Adam Rogoyski09f97962000-06-20 02:50:33 +0000650 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000651 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000652 }
653
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000654 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000655 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000656 * a) one word takes up the whole line with no starting spaces.
657 * - do nothing and return.
658 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000659 * - word starts new line.
660 * - keep white space on original line up to the cursor.
661 * *) cursor is after word at wrap point
662 * - either it's all white space after word, and this routine isn't called.
663 * - or we are actually in case 2 (2 words).
664 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000665 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000666 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000667 * - white space at end of original line is cleared, unless
668 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000669 * b) cursor is at the word at the wrap point.
670 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000671 * 1. pressed a space and at first character of wrap point word.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000672 * - white space on original line is kept to where cursor was.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000673 * 2. pressed non space (or space elsewhere).
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000674 * - white space at end of original line is cleared.
675 * c) cursor is past the word at the wrap point.
676 * - word at wrap point starts a new line.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000677 * - white space at end of original line is cleared
678 */
679
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000680 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000681
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000682 /* Category 1a: one word taking up the whole line with no beginning spaces. */
683 if ((last_word_end == -1) && (!isspace(inptr->data[0]))) {
684 for (i = current_word_end; i < len; i++) {
685 if (!isspace(inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000686 current_word_start = i;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000687 while (!isspace(inptr->data[i]) && (i < len)) {
688 i++;
689 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000690 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000691 current_word_end = i;
692 break;
693 }
694 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000695
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000696 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000697 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000698 return;
699 }
700 if (current_x >= last_word_end) {
701 right = (current_x - current_word_start) + 1;
702 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000703 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000704 }
705
706 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
707 strcpy(temp->data, &inptr->data[current_word_start]);
708 inptr->data = nrealloc(inptr->data, last_word_end + 2);
709 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000710 } else
711 /* Category 1b: one word on the line and word not taking up whole line
712 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000713 if (last_word_end == -1) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000714 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
715 strcpy(temp->data, &inptr->data[current_word_start]);
716
717 /* Inside word, remove it from original, and move cursor to right spot. */
718 if (current_x >= current_word_start) {
719 right = current_x - current_word_start;
720 current_x = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000721 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000722 }
723
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000724 null_at(inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000725
726 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
727 mark_beginbuf = temp;
728 mark_beginx = 0;
729 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000730 }
731
732 /* Category 2: two or more words on the line. */
733 else {
734
735 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000736 if (current_x < current_word_start) {
737 temp->data =
738 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
739 strcpy(temp->data, &inptr->data[current_word_start]);
740
741 if (!isspace(input_char)) {
742 i = current_word_start - 1;
743 while (isspace(inptr->data[i])) {
744 i--;
745 assert(i >= 0);
746 }
747 } else if (current_x <= last_word_end)
748 i = last_word_end - 1;
749 else
750 i = current_x;
751
752 inptr->data = nrealloc(inptr->data, i + 2);
753 inptr->data[i + 1] = 0;
754 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000755
756
757 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000758 else if ((current_x >= current_word_start)
759 && (current_x <= (current_word_end + 1))) {
760 temp->data =
761 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000762 strcpy(temp->data, &inptr->data[current_word_start]);
763
764 down = 1;
765
766 right = current_x - current_word_start;
767 i = current_word_start - 1;
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000768 if (isspace(input_char) && (current_x == current_word_start)) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000769 current_x = current_word_start;
770
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000771 null_at(inptr->data, current_word_start);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000772 } else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000773
774 while (isspace(inptr->data[i])) {
775 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000776 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000777 }
778 inptr->data = nrealloc(inptr->data, i + 2);
779 inptr->data[i + 1] = 0;
780 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000781 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000782
783
784 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000785 else {
786 temp->data =
787 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000788 strcpy(temp->data, &inptr->data[current_word_start]);
789
790 down = 1;
791 right = current_x - current_word_start;
792
793 current_x = current_word_start;
794 i = current_word_start - 1;
795
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000796 while (isspace(inptr->data[i])) {
797 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000798 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000799 inptr->data = nrealloc(inptr->data, i + 2);
800 inptr->data[i + 1] = 0;
801 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000802 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000803 }
804
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000805 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000806 if (ISSET(SAMELINEWRAP) && inptr->next) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000807 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
808 char *p =
809 nmalloc(strlen(temp->data) + strlen(inptr->next->data) + 2);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000810 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000811
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000812 strcpy(p, temp->data);
813 strcat(p, " ");
814 strcat(p, inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000815
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000816 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000817 inptr->next->data = p;
818
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000819 free(temp->data);
820 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000821
822
823 /* The next line line may need to be wrapped as well. */
824 current_y = old_y + 1;
825 current_x = strlen(inptr->next->data);
826 while (current_x >= 0) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000827 if (isspace(inptr->next->data[current_x])
828 && (current_x < fill)) break;
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000829 current_x--;
830 }
831 if (current_x >= 0)
832 check_wrap(inptr->next, ' ');
833
834 current_x = old_x;
835 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000836 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000837 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000838 else {
839 temp->prev = inptr;
840 temp->next = inptr->next;
841
842 if (inptr->next)
843 inptr->next->prev = temp;
844 inptr->next = temp;
845
846 if (!temp->next)
847 filebot = temp;
848
849 SET(SAMELINEWRAP);
850 }
851
852
853 totlines++;
Robert Siemborskia417ddc2000-07-24 23:18:48 +0000854 /* Everything about it makes me want this line here but it causes
855 * totsize to be high by one for some reason. Sigh. (Rob) */
856 /* totsize++; */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000857
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000858 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +0000859 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000860
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000861
862 /* Move the cursor to the new line if appropriate. */
863 if (down) {
864 do_right();
865 }
866
867 /* Move the cursor to the correct spot in the line if appropriate. */
868 while (right--) {
869 do_right();
870 }
871
Chris Allegretta234a34d2000-07-29 04:33:38 +0000872 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000873 reset_cursor();
874 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000875}
876
877/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000878void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000879{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000880 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000881#ifdef DEBUG
882 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
883 inptr->data);
884#endif
885
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000886 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000887 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000888 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000889 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000890
891 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000892 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000893
Adam Rogoyski09f97962000-06-20 02:50:33 +0000894 while (isspace(inptr->data[i]) && inptr->data[i])
895 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000896
Adam Rogoyski09f97962000-06-20 02:50:33 +0000897 if (!inptr->data[i])
898 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000899
Adam Rogoyski09f97962000-06-20 02:50:33 +0000900 /* String must be at least 1 character long. */
901 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
902 if (isspace(inptr->data[i])) {
903 if (!char_found)
904 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000905 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +0000906 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000907 } else
908 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000909 }
Adam Rogoyski09f97962000-06-20 02:50:33 +0000910
911 if (char_found == 2)
912 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000913 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000914}
915
916/* Stuff we do when we abort from programs and want to clean up the
917 * screen. This doesnt do much right now.
918 */
919void do_early_abort(void)
920{
921 blank_statusbar_refresh();
922}
923
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000924int 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;
Chris Allegrettada721be2000-07-31 01:26:42 +0000956 page_up_center();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000957 } 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 Allegretta8f6c0692000-07-19 01:16:18 +00001057 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001058}
1059
1060/*
1061 * This is Chris' very ugly spell function. Someone please make this
1062 * better =-)
1063 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001064int do_spell(void)
1065{
Chris Allegretta67105eb2000-07-03 03:18:32 +00001066#ifdef NANO_SMALL
1067 nano_small_msg();
1068 return 1;
1069#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001070 char *temp, *foo;
Robert Siemborski6af14312000-07-01 21:34:26 +00001071 int i, size;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001072
1073 if ((temp = tempnam(0, "nano.")) == NULL) {
1074 statusbar(_("Could not create a temporary filename: %s"),
1075 strerror(errno));
1076 return 0;
1077 }
1078 if (write_file(temp, 1) == -1)
1079 return 0;
1080
1081 if (alt_speller) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001082 size = strlen(temp) + strlen(alt_speller) + 2;
1083 foo = nmalloc(size);
1084 snprintf(foo, size, "%s %s", alt_speller, temp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001085 } else {
1086
1087 /* For now, we only try ispell because we're not capable of
1088 handling the normal spell program (yet...) */
Robert Siemborski6af14312000-07-01 21:34:26 +00001089 size = strlen(temp) + 8;
1090 foo = nmalloc(size);
1091 snprintf(foo, size, "ispell %s", temp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001092 }
1093
1094 endwin();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001095 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 }
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001107/* initscr(); */
1108 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001109
1110 free_filestruct(fileage);
1111 global_init();
1112 open_file(temp, 0, 1);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001113 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001114 set_modified();
1115 exit_spell(temp, foo);
1116 statusbar(_("Finished checking spelling"));
1117 return 1;
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001118#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001119}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001120
1121int do_exit(void)
1122{
1123 int i;
1124
1125 if (!ISSET(MODIFIED))
1126 finish(0);
1127
Chris Allegretta30885552000-07-14 01:20:12 +00001128 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001129 i = 1;
1130 } else {
1131 i =
1132 do_yesno(0, 0,
1133 _
1134 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1135 }
1136
1137#ifdef DEBUG
1138 dump_buffer(fileage);
1139#endif
1140
1141 if (i == 1) {
1142 if (do_writeout(1) > 0)
1143 finish(0);
1144 } else if (i == 0)
1145 finish(0);
1146 else
1147 statusbar(_("Cancelled"));
1148
1149 display_main_list();
1150 return 1;
1151}
1152
1153#ifndef NANO_SMALL
1154#ifdef NCURSES_MOUSE_VERSION
1155void do_mouse(void)
1156{
1157 MEVENT mevent;
1158
1159 if (getmouse(&mevent) == ERR)
1160 return;
1161
1162 /* If mouse not in edit window, return (add help selection later). */
1163 if (!wenclose(edit, mevent.y, mevent.x))
1164 return;
1165
1166 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1167 mevent.y -= 2;
1168
1169 /* Selecting where the cursor is sets the mark.
1170 * Selecting beyond the line length with the cursor at the end of the
1171 * line sets the mark as well.
1172 */
1173 if ((mevent.y == current_y) &&
1174 ((mevent.x == current_x) || (current_x == strlen(current->data)
1175 && (mevent.x >
1176 strlen(current->data))))) {
1177 if (ISSET(VIEW_MODE)) {
1178 print_view_warning();
1179 return;
1180 }
1181 do_mark();
1182 } else if (mevent.y > current_y) {
1183 while (mevent.y > current_y) {
1184 if (current->next != NULL)
1185 current = current->next;
1186 else
1187 break;
1188 current_y++;
1189 }
1190 } else if (mevent.y < current_y) {
1191 while (mevent.y < current_y) {
1192 if (current->prev != NULL)
1193 current = current->prev;
1194 else
1195 break;
1196 current_y--;
1197 }
1198 }
1199 current_x = mevent.x;
1200 if (current_x > strlen(current->data))
1201 current_x = strlen(current->data);
1202
1203 update_cursor();
1204 edit_refresh();
1205
1206}
1207#endif
1208#endif
1209
1210/* Handler for SIGHUP */
1211RETSIGTYPE handle_hup(int signal)
1212{
1213 write_file("nano.save", 0);
1214 finish(1);
1215}
1216
1217
1218void handle_sigwinch(int s)
1219{
1220#ifndef NANO_SMALL
1221 char *tty = NULL;
1222 int fd = 0;
1223 int result = 0;
1224 int i = 0;
1225 struct winsize win;
1226
1227 tty = ttyname(0);
1228 if (!tty)
1229 return;
1230 fd = open(tty, O_RDWR);
1231 if (fd == -1)
1232 return;
1233 result = ioctl(fd, TIOCGWINSZ, &win);
1234 if (result == -1)
1235 return;
1236
1237
1238 COLS = win.ws_col;
1239 LINES = win.ws_row;
1240
1241 center_x = COLS / 2;
1242 center_y = LINES / 2;
1243 editwinrows = LINES - 5 + no_help();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001244 fill = COLS - 8;
1245
1246 free(hblank);
1247 hblank = nmalloc(COLS + 1);
1248
1249 for (i = 0; i <= COLS - 1; i++)
1250 hblank[i] = ' ';
1251 hblank[i] = 0;
1252
1253#ifdef HAVE_NCURSES_H
1254 resizeterm(LINES, COLS);
1255#ifdef HAVE_WRESIZE
1256 if (wresize(topwin, 2, COLS) == ERR)
1257 die(_("Cannot resize top win"));
1258 if (mvwin(topwin, 0, 0) == ERR)
1259 die(_("Cannot move top win"));
1260 if (wresize(edit, editwinrows, COLS) == ERR)
1261 die(_("Cannot resize edit win"));
1262 if (mvwin(edit, 2, 0) == ERR)
1263 die(_("Cannot move edit win"));
1264 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1265 die(_("Cannot resize bottom win"));
1266 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1267 die(_("Cannot move bottom win"));
1268#endif /* HAVE_WRESIZE */
1269#endif /* HAVE_NCURSES_H */
1270
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001271 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001272
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001273 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001274 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001275 }
1276 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001277
1278 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001279 refresh();
Chris Allegretta97accc62000-06-19 05:45:52 +00001280 titlebar();
1281 edit_refresh();
1282 display_main_list();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001283 total_refresh();
1284#endif
1285}
1286
1287int do_tab(void)
1288{
1289 do_char('\t');
1290 return 1;
1291}
1292
1293#ifndef NANO_SMALL
1294int empty_line(const char *data)
1295{
1296 while (*data) {
1297 if (!isspace(*data))
1298 return 0;
1299
1300 data++;
1301 }
1302
1303 return 1;
1304}
1305
1306int no_spaces(const char *data)
1307{
1308 while (*data) {
1309 if (isspace(*data))
1310 return 0;
1311
1312 data++;
1313 }
1314
1315 return 1;
1316}
1317
1318void justify_format(char *data)
1319{
1320 int i = 0;
1321 int len = strlen(data);
1322
1323 /* Skip first character regardless and leading whitespace. */
1324 for (i = 1; i < len; i++) {
1325 if (!isspace(data[i]))
1326 break;
1327 }
1328
1329 i++; /* (i) is now at least 2. */
1330
1331 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
1332 for (; i < len; i++) {
1333 if (isspace(data[i]) && isspace(data[i - 1])
1334 && (data[i - 2] != '.')) {
1335 memmove(data + i, data + i + 1, len - i);
1336 len--;
1337 i--;
1338 }
1339 }
1340}
1341#endif
1342
1343int do_justify(void)
1344{
1345#ifndef NANO_SMALL
1346 int slen = 0; /* length of combined lines on one line. */
1347 int initial_y;
1348 filestruct *initial = NULL;
1349
1350 if (empty_line(current->data)) {
1351 /* Justify starting at first non-empty line. */
1352 do {
1353 if (!current->next)
1354 return 1;
1355
1356 current = current->next;
1357 current_y++;
1358 }
1359 while (empty_line(current->data));
1360 } else {
1361 /* Search back for the beginning of the paragraph, where
1362 * Paragraph is 1) A line with leading whitespace
1363 * or 2) A line following an empty line.
1364 */
1365 while (current->prev != NULL) {
1366 if (isspace(current->data[0]) || !current->data[0])
1367 break;
1368
1369 current = current->prev;
1370 current_y--;
1371 }
1372
1373 /* First line with leading whitespace may be empty. */
1374 if (empty_line(current->data)) {
1375 if (current->next) {
1376 current = current->next;
1377 current_y++;
1378 } else
1379 return 1;
1380 }
1381 }
1382 initial = current;
1383 initial_y = current_y;
1384
1385 set_modified();
1386 /* Put the whole paragraph into one big line. */
1387 while (current->next && !isspace(current->next->data[0])
1388 && current->next->data[0]) {
1389 filestruct *tmpnode = current->next;
1390 int len = strlen(current->data);
1391 int len2 = strlen(current->next->data);
1392
1393 /* length of both strings plus space between strings and ending \0. */
1394 current->data = nrealloc(current->data, len + len2 + 2);
1395 current->data[len++] = ' ';
1396 current->data[len] = '\0';
1397
1398 strncat(current->data, current->next->data, len2);
1399
1400 unlink_node(tmpnode);
1401 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001402 }
1403
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001404 totsize -= strlen(current->data);
1405
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001406 justify_format(current->data);
1407
1408 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001409 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001410
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001411 if((strlenpt(current->data) > (fill))
1412 && !no_spaces(current->data)) {
1413 do {
1414 int i = 0;
1415 int len2 = 0;
1416 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001417
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001418 /* Start at fill , unless line isn't that long (but it
1419 * appears at least fill long with tabs.
1420 */
1421 if (slen > fill)
1422 i = fill;
1423 else
1424 i = slen;
1425 for (; i > 0; i--) {
1426 if (isspace(current->data[i]) &&
1427 ((strlenpt(current->data) - strlen(current->data +i)) <=
1428 fill)) break;
1429 }
1430 if (!i)
1431 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001432
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001433 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001434
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001435 len2 = strlen(current->data + i + 1);
1436 tmpline->data = nmalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001437
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001438 /* Skip the white space in current. */
1439 memcpy(tmpline->data, current->data + i + 1, len2);
1440 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001441
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001442 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001443
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001444 tmpline->prev = current;
1445 tmpline->next = current->next;
1446 if (current->next != NULL)
1447 current->next->prev = tmpline;
1448
1449 current->next = tmpline;
1450 current = tmpline;
1451 slen -= i + 1;
1452 current_y++;
1453 } while ((strlenpt(current->data) > (fill))
1454 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001455 }
1456
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001457 if (current->next)
1458 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00001459 else
1460 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001461 current_x = 0;
1462 placewewant = 0;
1463
Adam Rogoyski09f97962000-06-20 02:50:33 +00001464 renumber(initial);
1465 totlines = filebot->lineno;
1466
1467 werase(edit);
1468
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001469 if ((current_y < 0) || (current_y >= editwinrows - 1)
1470 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001471 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001472 center_cursor();
1473 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001474 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001475 }
1476
Adam Rogoyski09f97962000-06-20 02:50:33 +00001477 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001478 statusbar("Justify Complete");
1479 return 1;
1480#else
1481 nano_small_msg();
1482 return 1;
1483#endif
1484}
1485
1486
1487void help_init(void)
1488{
1489 int i, sofar = 0;
1490 long allocsize = 1; /* How much space we're gonna need for the help text */
1491 char buf[BUFSIZ];
1492
1493 /* Compute the space needed for the shortcut lists - we add 15 to
1494 have room for the shortcut abbrev and its possible alternate keys */
1495 for (i = 0; i < MAIN_LIST_LEN; i++)
1496 if (main_list[i].help != NULL)
1497 allocsize += strlen(main_list[i].help) + 15;
1498
1499 allocsize += strlen(help_text_init);
1500
1501 if (help_text != NULL)
1502 free(help_text);
1503
1504 /* Allocate space for the help text */
1505 help_text = nmalloc(allocsize);
1506
1507 /* Now add the text we want */
1508 strcpy(help_text, help_text_init);
1509
1510 /* Now add our shortcut info */
1511 for (i = 0; i < MAIN_LIST_LEN; i++) {
Robert Siemborski6af14312000-07-01 21:34:26 +00001512 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001513
1514 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00001515 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001516 main_list[i].misc1 - KEY_F0);
1517 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001518 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001519
1520 if (main_list[i].altval > 0)
Robert Siemborski6af14312000-07-01 21:34:26 +00001521 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(@%c) ",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001522 main_list[i].altval - 32);
1523 else
Robert Siemborski6af14312000-07-01 21:34:26 +00001524 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001525
1526 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00001527 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001528
1529 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00001530 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001531 }
1532
1533}
1534
1535int main(int argc, char *argv[])
1536{
1537 int optchr;
1538 int kbinput; /* Input from keyboard */
1539 long startline = 0; /* Line to try and start at */
1540 struct sigaction act; /* For our lovely signals */
1541 int keyhandled = 0; /* Have we handled the keystroke yet? */
1542 int tmpkey = 0, i;
1543 char *argv0;
1544 struct termios term;
1545
1546#ifdef HAVE_GETOPT_LONG
1547 int option_index = 0;
1548 struct option long_options[] = {
Chris Allegretta47805612000-07-07 02:35:34 +00001549#ifdef _POSIX_VERSION
Chris Allegretta9fc8d432000-07-07 01:49:52 +00001550 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00001551#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001552 {"version", 0, 0, 'V'},
1553 {"const", 0, 0, 'c'},
1554 {"suspend", 0, 0, 'z'},
1555 {"nowrap", 0, 0, 'w'},
1556 {"nohelp", 0, 0, 'x'},
1557 {"help", 0, 0, 'h'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00001558#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00001559 {"cut", 0, 0, 'k'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00001560#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001561 {"autoindent", 0, 0, 'i'},
1562 {"tempfile", 0, 0, 't'},
1563 {"speller", 1, 0, 's'},
1564 {"fill", 1, 0, 'r'},
1565 {"mouse", 0, 0, 'm'},
1566 {"pico", 0, 0, 'p'},
1567 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00001568 {"tabsize", 1, 0, 'T'},
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 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00001591 tabsize = atoi(optarg);
1592 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00001593 usage(); /* To stop bogus data for tab width */
1594 finish(1);
1595 }
1596 break;
Chris Allegretta47805612000-07-07 02:35:34 +00001597#ifdef _POSIX_VERSION
Chris Allegretta9fc8d432000-07-07 01:49:52 +00001598 case 'R':
1599 SET(USE_REGEXP);
1600 break;
Chris Allegretta47805612000-07-07 02:35:34 +00001601#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001602 case 'V':
1603 version();
1604 exit(0);
1605 case 'c':
1606 SET(CONSTUPDATE);
1607 break;
1608 case 'h':
1609 case '?':
1610 usage();
1611 exit(0);
1612 case 'i':
1613 SET(AUTOINDENT);
1614 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00001615#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00001616 case 'k':
1617 SET(CUT_TO_END);
1618 break;
Chris Allegretta18bd0292000-07-28 01:18:10 +00001619#else
1620 case 'k':
1621 usage(); /* Oops! You dont really have that option */
1622 finish(1);
Chris Allegrettad19e9912000-07-12 18:14:51 +00001623#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001624 case 'l':
1625 UNSET(FOLLOW_SYMLINKS);
1626 break;
1627 case 'm':
1628 SET(USE_MOUSE);
1629 break;
1630 case 'p':
1631 SET(PICO_MSGS);
1632 break;
1633 case 'r':
1634 fill = atoi(optarg);
1635 if (fill <= 0) {
1636 usage(); /* To stop bogus data (like a string) */
1637 finish(1);
1638 }
1639 break;
1640 case 's':
1641 alt_speller = nmalloc(strlen(optarg) + 1);
1642 strcpy(alt_speller, optarg);
1643 break;
1644 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00001645 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001646 break;
1647 case 'v':
1648 SET(VIEW_MODE);
1649 break;
1650 case 'w':
1651 SET(NO_WRAP);
1652 break;
1653 case 'x':
1654 SET(NO_HELP);
1655 break;
1656 case 'z':
1657 SET(SUSPEND);
1658 break;
1659 default:
1660 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001661 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001662 }
1663
1664 }
1665
1666 argv0 = strrchr(argv[0], '/');
1667 if ((argv0 && strstr(argv0, "pico"))
1668 || (!argv0 && strstr(argv[0], "pico")))
1669 SET(PICO_MSGS);
1670
1671 filename = nmalloc(PATH_MAX);
1672 strcpy(filename, "");
1673
1674 /* See if there's a non-option in argv (first non-option is the
1675 filename, if +LINE is not given) */
1676 if (argc == 1 || argc <= optind)
1677 strcpy(filename, "");
1678 else {
1679 /* Look for the +line flag... */
1680 if (argv[optind][0] == '+') {
1681 startline = atoi(&argv[optind][1]);
1682 optind++;
1683 if (argc == 1 || argc <= optind)
1684 strcpy(filename, "");
1685 else
1686 strncpy(filename, argv[optind], 132);
1687 } else
1688 strncpy(filename, argv[optind], 132);
1689
1690 }
1691
1692
1693 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001694 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001695
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001696 term = oldterm;
1697 term.c_cc[VINTR] = _POSIX_VDISABLE;
1698 term.c_cc[VQUIT] = _POSIX_VDISABLE;
1699 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001700 tcsetattr(0, TCSANOW, &term);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001701
1702 /* now ncurses init stuff... */
1703 initscr();
1704 savetty();
1705 nonl();
1706 cbreak();
1707 noecho();
1708 timeout(0);
1709
1710 /* Set up some global variables */
1711 global_init();
1712 shortcut_init();
1713 init_help_msg();
1714 help_init();
1715
1716 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001717 memset(&act, 0, sizeof(struct sigaction));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001718 act.sa_handler = SIG_IGN;
1719 sigaction(SIGINT, &act, NULL);
1720 sigaction(SIGQUIT, &act, NULL);
1721
1722 if (!ISSET(SUSPEND))
1723 sigaction(SIGTSTP, &act, NULL);
1724
1725 /* Trap SIGHUP cuz we want to write the file out. */
1726 act.sa_handler = handle_hup;
1727 sigaction(SIGHUP, &act, NULL);
1728
1729 act.sa_handler = handle_sigwinch;
1730 sigaction(SIGWINCH, &act, NULL);
1731
1732#ifdef DEBUG
1733 fprintf(stderr, _("Main: set up windows\n"));
1734#endif
1735
1736 /* Setup up the main text window */
1737 edit = newwin(editwinrows, COLS, 2, 0);
1738 keypad(edit, TRUE);
1739
1740#ifndef NANO_SMALL
1741#ifdef NCURSES_MOUSE_VERSION
1742 if (ISSET(USE_MOUSE)) {
1743 mousemask(BUTTON1_RELEASED, NULL);
1744 mouseinterval(50);
1745 }
1746#endif
1747#endif
1748
1749 /* And the other windows */
1750 topwin = newwin(2, COLS, 0, 0);
1751 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
1752 keypad(bottomwin, TRUE);
1753
1754#ifdef DEBUG
1755 fprintf(stderr, _("Main: bottom win\n"));
1756#endif
1757 /* Set up up bottom of window */
1758 display_main_list();
1759
1760#ifdef DEBUG
1761 fprintf(stderr, _("Main: open file\n"));
1762#endif
1763
1764 titlebar();
1765 if (argc == 1)
1766 new_file();
1767 else
1768 open_file(filename, 0, 0);
1769
1770 if (startline > 0)
1771 do_gotoline(startline);
1772 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00001773 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001774
Robert Siemborski6967eec2000-07-08 14:23:32 +00001775 edit_refresh();
1776 reset_cursor();
1777
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001778 while (1) {
1779 kbinput = wgetch(edit);
1780 if (kbinput == 27) { /* Grab Alt-key stuff first */
1781 switch (kbinput = wgetch(edit)) {
1782 case 91:
1783
1784 switch (kbinput = wgetch(edit)) {
1785 case 'A':
1786 kbinput = KEY_UP;
1787 break;
1788 case 'B':
1789 kbinput = KEY_DOWN;
1790 break;
1791 case 'C':
1792 kbinput = KEY_RIGHT;
1793 break;
1794 case 'D':
1795 kbinput = KEY_LEFT;
1796 break;
1797 case 'H':
1798 kbinput = KEY_HOME;
1799 break;
1800 case 'F':
1801 kbinput = KEY_END;
1802 break;
1803 case 49: /* X window F-keys */
1804 tmpkey = wgetch(edit);
1805 kbinput = KEY_F(tmpkey) - 48;
1806 wgetch(edit); /* Junk character */
1807 break;
1808 case 53: /* page up */
1809 kbinput = KEY_PPAGE;
1810 if ((kbinput = wgetch(edit)) == 126)
1811 kbinput = KEY_PPAGE; /* Ignore extra tilde */
1812 else { /* I guess this could happen ;-) */
1813 ungetch(kbinput);
1814 continue;
1815 }
1816 break;
1817 case 54: /* page down */
1818 kbinput = KEY_NPAGE;
1819 if ((kbinput = wgetch(edit)) == 126)
1820 kbinput = KEY_NPAGE; /* Same thing here */
1821 else {
1822 ungetch(kbinput);
1823 continue;
1824 }
1825 break;
1826
1827 default:
1828#ifdef DEBUG
1829 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
1830 kbinput, kbinput);
1831#endif
1832 break;
1833 }
1834 break;
1835 default:
1836
1837 /* Check for the altkey defs.... */
1838 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
1839 if (kbinput == main_list[i].altval ||
1840 kbinput == main_list[i].altval - 32) {
1841 kbinput = main_list[i].val;
1842 break;
1843 }
1844#ifdef DEBUG
1845 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
1846 kbinput);
1847#endif
1848 break;
1849 }
1850 }
1851 /* Look through the main shortcut list to see if we've hit a
1852 shortcut key */
1853 for (i = 0; i < MAIN_LIST_LEN; i++) {
1854 if (kbinput == main_list[i].val ||
1855 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
1856 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
1857 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
1858 print_view_warning();
1859 else
1860 main_list[i].func();
1861 keyhandled = 1;
1862 }
1863 }
1864 /* Last gasp, stuff that's not in the main lists */
1865 if (!keyhandled)
1866 switch (kbinput) {
1867#ifndef NANO_SMALL
1868#ifdef NCURSES_MOUSE_VERSION
1869 case KEY_MOUSE:
1870 do_mouse();
1871 break;
1872#endif
1873#endif
1874 case 0: /* Erg */
1875 do_next_word();
1876 break;
1877 case 331: /* Stuff that we don't want to do squat */
1878 case -1:
1879 case 410: /* Must ignore this, it gets sent when we resize */
1880 break;
1881 default:
1882#ifdef DEBUG
1883 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
1884#endif
1885 /* We no longer stop unhandled sequences so that people with
1886 odd character sets can type... */
1887
1888 if (ISSET(VIEW_MODE)) {
1889 print_view_warning();
1890 break;
1891 }
1892 do_char(kbinput);
1893 }
1894 if (ISSET(CONSTUPDATE))
1895 do_cursorpos();
1896
1897 reset_cursor();
1898 wrefresh(edit);
1899 keyhandled = 0;
1900 }
1901
1902 getchar();
1903 finish(0);
1904
1905}