blob: 054775f71ae05b47eccbd0d4556627b502a68ce9 [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>
Chris Allegretta08020882001-01-29 23:37:54 +000026#include <setjmp.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000027#include <unistd.h>
28#include <string.h>
29#include <fcntl.h>
30#include <sys/stat.h>
31#include <sys/ioctl.h>
32#include <sys/param.h>
Chris Allegretta27eb13f2000-11-05 16:52:21 +000033#include <sys/types.h>
34#include <sys/wait.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000035#include <errno.h>
36#include <ctype.h>
37#include <locale.h>
38#include <limits.h>
Adam Rogoyski77f36de2000-06-07 03:56:54 +000039#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000040
41#include "config.h"
42#include "proto.h"
43#include "nano.h"
44
45#ifndef NANO_SMALL
46#include <libintl.h>
47#define _(string) gettext(string)
48#else
49#define _(string) (string)
50#endif
51
52#ifdef HAVE_TERMIOS_H
53#include <termios.h>
54#endif
55
56#ifdef HAVE_TERMIO_H
57#include <termio.h>
58#endif
59
60#ifdef HAVE_GETOPT_H
61#include <getopt.h>
62#endif
63
64/* Former globals, now static */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000065int fill = 0; /* Fill - where to wrap lines, basically */
Rocco Corsiaf5c3022001-01-12 07:51:05 +000066
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000067struct termios oldterm; /* The user's original term settings */
Chris Allegretta18f8be02000-09-04 03:20:38 +000068static struct sigaction act; /* For all out fun signal handlers */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000069
Rocco Corsiaf5c3022001-01-12 07:51:05 +000070#ifndef DISABLE_HELP
Chris Allegretta6b58acd2001-04-12 03:01:53 +000071static char *help_text_init = ""; /* Initial message, not including shortcuts */
Chris Allegretta65121632000-12-18 07:05:27 +000072#endif
73
Chris Allegretta27eb13f2000-11-05 16:52:21 +000074char *last_search = NULL; /* Last string we searched for */
75char *last_replace = NULL; /* Last replacement string */
76int search_last_line; /* Is this the last search line? */
77
Chris Allegretta08020882001-01-29 23:37:54 +000078static sigjmp_buf jmpbuf; /* Used to return to mainloop after SIGWINCH */
79
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000080/* What we do when we're all set to exit */
81RETSIGTYPE finish(int sigage)
82{
Chris Allegrettac08f50d2001-01-06 18:12:43 +000083
84 keypad(edit, TRUE);
85 keypad(bottomwin, TRUE);
86
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000087 if (!ISSET(NO_HELP)) {
88 mvwaddstr(bottomwin, 1, 0, hblank);
89 mvwaddstr(bottomwin, 2, 0, hblank);
Chris Allegretta4da1fc62000-06-21 03:00:43 +000090 } else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000091 mvwaddstr(bottomwin, 0, 0, hblank);
Chris Allegretta6b58acd2001-04-12 03:01:53 +000092
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000093 wrefresh(bottomwin);
94 endwin();
95
96 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +000097 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000098
99 exit(sigage);
100}
101
102/* Die (gracefully?) */
103void die(char *msg, ...)
104{
105 va_list ap;
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000106 char *name;
107 int i;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000108
109 va_start(ap, msg);
110 vfprintf(stderr, msg, ap);
111 va_end(ap);
112
113 /* if we can't save we have REAL bad problems,
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000114 * but we might as well TRY. */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000115 if (filename[0] == '\0') {
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000116 name = "nano.save";
117 i = write_file(name, 1);
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000118 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000119
Chris Allegrettae7a58932000-12-02 02:36:22 +0000120 char *buf = nmalloc(strlen(filename) + 6);
121 strcpy(buf, filename);
122 strcat(buf, ".save");
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000123 i = write_file(buf, 1);
124 name = buf;
Robert Siemborskifcf32bf2000-07-17 03:04:54 +0000125 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000126 /* Restore the old term settings */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000127 tcsetattr(0, TCSANOW, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000128
129 clear();
130 refresh();
131 resetty();
132 endwin();
133
134 fprintf(stderr, msg);
Chris Allegretta3dbb2782000-12-02 04:36:50 +0000135 if (i != -1)
136 fprintf(stderr, _("\nBuffer written to %s\n"), name);
137 else
Chris Allegretta9756d622000-12-03 03:06:45 +0000138 fprintf(stderr, _("\nNo %s written (file exists?)\n"), name);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000139
140 exit(1); /* We have a problem: exit w/ errorlevel(1) */
141}
142
Chris Allegrettae61e8302001-01-14 05:18:27 +0000143/* Die with an error message that the screen was too small if, well, the
144 screen is too small */
145void die_too_small(void)
146{
147 char *too_small_msg = _("Window size is too small for Nano...");
148
149 die(too_small_msg);
150
151}
152
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000153void print_view_warning(void)
154{
155 statusbar(_("Key illegal in VIEW mode"));
156}
157
Chris Allegretta1a6e9042000-12-14 13:56:28 +0000158void clear_filename(void)
159{
160 if (filename != NULL)
161 free(filename);
162 filename = nmalloc(1);
163 filename[0] = 0;
164}
Chris Allegretta1cc0b7f2000-11-03 01:29:04 +0000165
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000166/* Initialize global variables - no better way for now */
167void global_init(void)
168{
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000169 current_x = 0;
170 current_y = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000171
172 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
173 die_too_small();
174
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000175 fileage = NULL;
176 cutbuffer = NULL;
177 current = NULL;
178 edittop = NULL;
179 editbot = NULL;
180 totlines = 0;
181 placewewant = 0;
Chris Allegrettae61e8302001-01-14 05:18:27 +0000182
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000183 if (!fill)
Chris Allegrettae61e8302001-01-14 05:18:27 +0000184 fill = COLS - CHARS_FROM_EOL;
185
186 if (fill < MIN_FILL_LENGTH)
187 die_too_small();
188
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000189 hblank = nmalloc(COLS + 1);
Chris Allegretta0a06e072001-01-23 02:35:04 +0000190 memset(hblank, ' ', COLS);
191 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000192}
193
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000194#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000195void init_help_msg(void)
196{
197
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000198 help_text_init =
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000199 _(" nano help text\n\n "
200 "The nano editor is designed to emulate the functionality and "
201 "ease-of-use of the UW Pico text editor. There are four main "
202 "sections of the editor: The top line shows the program "
203 "version, the current filename being edited, and whether "
204 "or not the file has been modified. Next is the main editor "
205 "window showing the file being edited. The status line is "
206 "the third line from the bottom and shows important messages. "
207 "The bottom two lines show the most commonly used shortcuts "
208 "in the editor.\n\n "
209 "The notation for shortcuts is as follows: Control-key "
Chris Allegrettae49f1232000-09-02 07:20:39 +0000210 "sequences are notated with a caret (^) symbol and are entered "
Chris Allegrettad56bd792000-09-02 07:27:10 +0000211 "with the Control (Ctrl) key. Escape-key sequences are notated "
212 "with the Meta (M) symbol and can be entered using either the "
213 "Esc, Alt or Meta key depending on your keyboard setup. The "
214 "following keystrokes are available in the main editor window. "
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000215 "Optional keys are shown in parentheses:\n\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000216
217}
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000218#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000219
220/* Make a copy of a node to a pointer (space will be malloc()ed) */
221filestruct *copy_node(filestruct * src)
222{
223 filestruct *dst;
224
225 dst = nmalloc(sizeof(filestruct));
226 dst->data = nmalloc(strlen(src->data) + 1);
227
228 dst->next = src->next;
229 dst->prev = src->prev;
230
231 strcpy(dst->data, src->data);
232 dst->lineno = src->lineno;
233
234 return dst;
235}
236
237/* Unlink a node from the rest of the struct */
238void unlink_node(filestruct * fileptr)
239{
240 if (fileptr->prev != NULL)
241 fileptr->prev->next = fileptr->next;
242
243 if (fileptr->next != NULL)
244 fileptr->next->prev = fileptr->prev;
245}
246
247void delete_node(filestruct * fileptr)
248{
Chris Allegretta17dcb722001-01-20 21:40:07 +0000249 if (fileptr == NULL)
250 return;
251
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000252 if (fileptr->data != NULL)
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000253 free(fileptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000254 free(fileptr);
255}
256
257/* Okay, now let's duplicate a whole struct! */
258filestruct *copy_filestruct(filestruct * src)
259{
260 filestruct *dst, *tmp, *head, *prev;
261
262 head = copy_node(src);
263 dst = head; /* Else we barf on copying just one line */
264 head->prev = NULL;
265 tmp = src->next;
266 prev = head;
267
268 while (tmp != NULL) {
269 dst = copy_node(tmp);
270 dst->prev = prev;
271 prev->next = dst;
272
273 prev = dst;
274 tmp = tmp->next;
275 }
276
277 dst->next = NULL;
278 return head;
279}
280
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000281int free_filestruct(filestruct * src)
282{
283 filestruct *fileptr = src;
284
285 if (src == NULL)
286 return 0;
287
288 while (fileptr->next != NULL) {
289 fileptr = fileptr->next;
Chris Allegretta17dcb722001-01-20 21:40:07 +0000290 delete_node(fileptr->prev);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000291
292#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000293 fprintf(stderr, _("delete_node(): free'd a node, YAY!\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000294#endif
295 }
Chris Allegretta17dcb722001-01-20 21:40:07 +0000296 delete_node(fileptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000297#ifdef DEBUG
Chris Allegretta17dcb722001-01-20 21:40:07 +0000298 fprintf(stderr, _("delete_node(): free'd last node.\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000299#endif
300
301 return 1;
302}
303
304int renumber_all(void)
305{
306 filestruct *temp;
307 long i = 1;
308
309 for (temp = fileage; temp != NULL; temp = temp->next) {
310 temp->lineno = i++;
311 }
312
313 return 0;
314}
315
316int renumber(filestruct * fileptr)
317{
318 filestruct *temp;
319
320 if (fileptr == NULL || fileptr->prev == NULL || fileptr == fileage) {
321 renumber_all();
322 return 0;
323 }
324 for (temp = fileptr; temp != NULL; temp = temp->next) {
Chris Allegretta5146fec2000-12-10 05:44:02 +0000325 if (temp->prev != NULL)
326 temp->lineno = temp->prev->lineno + 1;
327 else
328 temp->lineno = 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000329 }
330
331 return 0;
332}
333
334/* Fix the memory allocation for a string */
335void align(char **strp)
336{
337 /* There was a serious bug here: the new address was never
338 stored anywhere... */
339
340 *strp = nrealloc(*strp, strlen(*strp) + 1);
341}
342
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000343/* Null a string at a certain index and align it */
344void null_at(char *data, int index)
345{
346 data[index] = 0;
347 align(&data);
348}
349
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000350void usage(void)
351{
352#ifdef HAVE_GETOPT_LONG
353 printf(_("Usage: nano [GNU long option] [option] +LINE <file>\n\n"));
354 printf(_("Option Long option Meaning\n"));
Chris Allegretta6724a7e2000-06-19 23:19:07 +0000355 printf(_
Chris Allegrettae9a2d032001-01-21 16:08:21 +0000356 (" -T [num] --tabsize=[num] Set width of a tab to num\n"));
Chris Allegretta805c26d2000-09-06 13:39:17 +0000357#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000358 printf(_
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000359 (" -R --regexp Use regular expressions for search\n"));
Chris Allegretta47805612000-07-07 02:35:34 +0000360#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000361 printf
362 (_
363 (" -V --version Print version information and exit\n"));
364 printf(_
365 (" -c --const Constantly show cursor position\n"));
366 printf(_
367 (" -h --help Show this message\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000368 printf(_
369 (" -i --autoindent Automatically indent new lines\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000370#ifndef NANO_SMALL
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000371 printf(_
Chris Allegretta627de192000-07-12 02:09:17 +0000372 (" -k --cut Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000373#endif
Chris Allegretta627de192000-07-12 02:09:17 +0000374 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000375 (" -l --nofollow Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000376#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000377#ifdef NCURSES_MOUSE_VERSION
378 printf(_(" -m --mouse Enable mouse\n"));
379#endif
380#endif
Chris Allegrettad55655f2000-12-27 03:36:47 +0000381 printf(_
382 (" -p --pico Emulate Pico as closely as possible\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000383 printf
384 (_
385 (" -r [#cols] --fill=[#cols] Set fill cols to (wrap lines at) #cols\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000386#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000387 printf(_
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000388 (" -s [prog] --speller=[prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000389#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000390 printf(_
391 (" -t --tempfile Auto save on exit, don't prompt\n"));
392 printf(_
393 (" -v --view View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000394#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000395 printf(_
396 (" -w --nowrap Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000397#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000398 printf(_
399 (" -x --nohelp Don't show help window\n"));
400 printf(_
401 (" -z --suspend Enable suspend\n"));
402 printf(_
403 (" +LINE Start at line number LINE\n"));
404#else
405 printf(_("Usage: nano [option] +LINE <file>\n\n"));
406 printf(_("Option Meaning\n"));
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000407 printf(_(" -T [num] Set width of a tab to num\n"));
Chris Allegretta9fc8d432000-07-07 01:49:52 +0000408 printf(_(" -R Use regular expressions for search\n"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000409 printf(_(" -V Print version information and exit\n"));
410 printf(_(" -c Constantly show cursor position\n"));
411 printf(_(" -h Show this message\n"));
Chris Allegrettad55655f2000-12-27 03:36:47 +0000412 printf(_(" -i Automatically indent new lines\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000413#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +0000414 printf(_(" -k Let ^K cut from cursor to end of line\n"));
Chris Allegrettad19e9912000-07-12 18:14:51 +0000415#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000416 printf(_
Chris Allegretta71348ee2000-10-02 04:21:23 +0000417 (" -l Don't follow symbolic links, overwrite\n"));
Chris Allegretta84de5522001-04-12 14:51:48 +0000418#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000419#ifdef NCURSES_MOUSE_VERSION
420 printf(_(" -m Enable mouse\n"));
421#endif
422#endif
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +0000423 printf(_(" -p Emulate Pico as closely as possible\n"));
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000424 printf(_
425 (" -r [#cols] Set fill cols to (wrap lines at) #cols\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000426#ifndef DISABLE_SPELLER
Chris Allegrettad55655f2000-12-27 03:36:47 +0000427 printf(_(" -s [prog] Enable alternate speller\n"));
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000428#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000429 printf(_(" -t Auto save on exit, don't prompt\n"));
430 printf(_(" -v View (read only) mode\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000431#ifndef DISABLE_WRAPPING
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000432 printf(_(" -w Don't wrap long lines\n"));
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000433#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000434 printf(_(" -x Don't show help window\n"));
435 printf(_(" -z Enable suspend\n"));
436 printf(_(" +LINE Start at line number LINE\n"));
437#endif
438 exit(0);
439}
440
441void version(void)
442{
Chris Allegrettac46dd812001-02-14 14:28:27 +0000443 printf(_(" GNU nano version %s (compiled %s, %s)\n"),
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000444 VERSION, __TIME__, __DATE__);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000445 printf(_
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000446 (" Email: nano@nano-editor.org Web: http://www.nano-editor.org"));
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000447 printf(_("\n Compiled options:"));
Chris Allegrettaff269f82000-12-01 18:46:01 +0000448
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000449#ifdef NANO_EXTRA
450 printf(" --enable-extra");
451#endif
Chris Allegrettab881d3e2001-04-18 04:34:43 +0000452#ifdef ENABLE_NANORC
453 printf(" --enable-nanorc");
454#endif
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000455
456#ifdef NANO_SMALL
457 printf(" --enable-tiny");
458#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000459#ifdef DISABLE_BROWSER
Chris Allegretta6636dc32001-01-05 05:41:07 +0000460 printf(" --disable-browser");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000461#endif
462#ifdef DISABLE_TABCOMP
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000463 printf(" --disable-tabcomp");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000464#endif
465#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +0000466 printf(" --disable-justify");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000467#endif
468#ifdef DISABLE_SPELLER
Chris Allegretta7b36c522000-12-06 01:08:10 +0000469 printf(" --disable-speller");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000470#endif
471#ifdef DISABLE_HELP
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000472 printf(" --disable-help");
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000473#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000474#ifdef DISABLE_MOUSE
475 printf(" --disable-mouse");
Chris Allegrettab7d00ef2000-12-18 05:36:51 +0000476#endif
Chris Allegretta84de5522001-04-12 14:51:48 +0000477#endif /* NANO_SMALL */
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000478
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000479#ifdef DISABLE_WRAPPING
480 printf(" --disable-wrapping");
481#endif
Chris Allegretta8a0de3b2000-11-24 20:45:14 +0000482#ifdef USE_SLANG
483 printf(" --with-slang");
484#endif
485 printf("\n");
486
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000487}
488
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000489filestruct *make_new_node(filestruct * prevnode)
490{
491 filestruct *newnode;
492
493 newnode = nmalloc(sizeof(filestruct));
494 newnode->data = NULL;
495
496 newnode->prev = prevnode;
497 newnode->next = NULL;
498
499 if (prevnode != NULL)
500 newnode->lineno = prevnode->lineno + 1;
501
502 return newnode;
503}
504
Chris Allegretta7975ed82000-07-28 00:58:35 +0000505/* Splice a node into an existing filestruct */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000506void splice_node(filestruct * begin, filestruct * newnode,
507 filestruct * end)
Chris Allegretta7975ed82000-07-28 00:58:35 +0000508{
Chris Allegrettae3167732001-03-18 16:59:34 +0000509 newnode->next = end;
510 newnode->prev = begin;
511 begin->next = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000512 if (end != NULL)
Chris Allegrettae3167732001-03-18 16:59:34 +0000513 end->prev = newnode;
Chris Allegretta7975ed82000-07-28 00:58:35 +0000514}
515
Chris Allegrettae3167732001-03-18 16:59:34 +0000516int do_mark(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000517{
518#ifdef NANO_SMALL
Rocco Corsiaf5c3022001-01-12 07:51:05 +0000519 nano_disabled_msg();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000520#else
521 if (!ISSET(MARK_ISSET)) {
522 statusbar(_("Mark Set"));
523 SET(MARK_ISSET);
524 mark_beginbuf = current;
525 mark_beginx = current_x;
526 } else {
527 statusbar(_("Mark UNset"));
528 UNSET(MARK_ISSET);
529 mark_beginbuf = NULL;
530 mark_beginx = 0;
531
532 edit_refresh();
533 }
534#endif
535 return 1;
536}
537
538int no_help(void)
539{
540 if ISSET
541 (NO_HELP)
542 return 2;
543 else
544 return 0;
545}
546
Chris Allegretta3bc8c722000-12-10 17:03:25 +0000547#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP)
Chris Allegrettaff269f82000-12-01 18:46:01 +0000548void nano_disabled_msg(void)
549{
550 statusbar("Sorry, support for this function has been disabled");
551}
Chris Allegretta4eb7aa02000-12-01 18:57:11 +0000552#endif
Chris Allegrettaff269f82000-12-01 18:46:01 +0000553
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000554/* The user typed a printable character; add it to the edit buffer */
555void do_char(char ch)
556{
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000557 /* magic-line: when a character is inserted on the current magic line,
558 * it means we need a new one! */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000559 if (filebot == current && current->data[0] == '\0') {
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000560 new_magicline();
Chris Allegretta28a0f892000-07-05 22:47:54 +0000561 fix_editbot();
Robert Siemborski63b3d7e2000-07-04 22:15:39 +0000562 }
563
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000564 /* More dangerousness fun =) */
565 current->data = nrealloc(current->data, strlen(current->data) + 2);
566 memmove(&current->data[current_x + 1],
567 &current->data[current_x],
568 strlen(current->data) - current_x + 1);
569 current->data[current_x] = ch;
570 do_right();
571
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000572#ifndef DISABLE_WRAPPING
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000573 if (!ISSET(NO_WRAP) && (ch != '\t'))
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000574 check_wrap(current, ch);
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000575#endif
576
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000577 set_modified();
578 check_statblank();
579 UNSET(KEEP_CUTBUFFER);
580 totsize++;
581
582}
583
584/* Someone hits return *gasp!* */
585int do_enter(filestruct * inptr)
586{
Chris Allegrettae3167732001-03-18 16:59:34 +0000587 filestruct *newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000588 char *tmp, *spc;
589 int extra = 0;
590
Chris Allegrettae3167732001-03-18 16:59:34 +0000591 newnode = make_new_node(inptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000592 tmp = &current->data[current_x];
593 current_x = 0;
594
595 /* Do auto-indenting, like the neolithic Turbo Pascal editor */
596 if (ISSET(AUTOINDENT)) {
597 spc = current->data;
598 if (spc) {
599 while ((*spc == ' ') || (*spc == '\t')) {
600 extra++;
601 spc++;
602 current_x++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000603 totsize++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000604 }
Chris Allegrettae3167732001-03-18 16:59:34 +0000605 newnode->data = nmalloc(strlen(tmp) + extra + 1);
606 strncpy(newnode->data, current->data, extra);
607 strcpy(&newnode->data[extra], tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000608 }
609 } else {
Chris Allegrettae3167732001-03-18 16:59:34 +0000610 newnode->data = nmalloc(strlen(tmp) + 1);
611 strcpy(newnode->data, tmp);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000612 }
613 *tmp = 0;
614
Chris Allegrettada721be2000-07-31 01:26:42 +0000615 if (inptr->next == NULL) {
Chris Allegrettae3167732001-03-18 16:59:34 +0000616 filebot = newnode;
617 editbot = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000618 }
Chris Allegrettae3167732001-03-18 16:59:34 +0000619 splice_node(inptr, newnode, inptr->next);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000620
621 totsize++;
622 renumber(current);
Chris Allegrettae3167732001-03-18 16:59:34 +0000623 current = newnode;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000624 align(&current->data);
625
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000626 /* The logic here is as follows:
627 * -> If we are at the bottom of the buffer, we want to recenter
628 * (read: rebuild) the screen and forcably move the cursor.
629 * -> otherwise, we want simply to redraw the screen and update
630 * where we think the cursor is.
631 */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000632 if (current_y == editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +0000633 edit_update(current, CENTER);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000634 reset_cursor();
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000635 } else {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000636 current_y++;
Robert Siemborskidd53ec22000-07-04 02:35:19 +0000637 edit_refresh();
638 update_cursor();
639 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000640
641 totlines++;
642 set_modified();
643
Chris Allegrettab0ae3932000-06-15 23:39:14 +0000644 placewewant = xplustabs();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000645 return 1;
646}
647
648int do_enter_void(void)
649{
650 return do_enter(current);
651}
652
653void do_next_word(void)
654{
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000655 filestruct *fileptr, *old;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000656 int i;
657
658 if (current == NULL)
659 return;
660
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000661 old = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000662 i = current_x;
663 for (fileptr = current; fileptr != NULL; fileptr = fileptr->next) {
664 if (fileptr == current) {
665 while (isalnum((int) fileptr->data[i])
666 && fileptr->data[i] != 0)
667 i++;
668
669 if (fileptr->data[i] == 0) {
670 i = 0;
671 continue;
672 }
673 }
674 while (!isalnum((int) fileptr->data[i]) && fileptr->data[i] != 0)
675 i++;
676
677 if (fileptr->data[i] != 0)
678 break;
679
680 i = 0;
681 }
682 if (fileptr == NULL)
683 current = filebot;
684 else
685 current = fileptr;
686
687 current_x = i;
688 placewewant = xplustabs();
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000689
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000690 if (current->lineno >= editbot->lineno)
Chris Allegretta234a34d2000-07-29 04:33:38 +0000691 edit_update(current, CENTER);
Chris Allegretta9e2934f2000-12-01 23:49:48 +0000692 else {
693 /* If we've jumped lines, refresh the old line. We can't just use
694 * current->prev here, because we may have skipped over some blank
695 * lines, in which case the previous line is the wrong one.
696 */
697 if (current != old)
698 update_line(old, 0);
699
700 update_line(current, current_x);
701 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000702
703}
704
Chris Allegrettacef7fbb2001-04-02 05:36:08 +0000705#ifndef DISABLE_WRAPPING
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000706void do_wrap(filestruct * inptr, char input_char)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000707{
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000708 int i = 0; /* Index into ->data for line. */
709 int i_tabs = 0; /* Screen position of ->data[i]. */
710 int last_word_end = -1; /* Location of end of last word found. */
711 int current_word_start = -1; /* Location of start of current word. */
712 int current_word_start_t = -1; /* Location of start of current word screen position. */
713 int current_word_end = -1; /* Location of end of current word */
714 int current_word_end_t = -1; /* Location of end of current word screen position. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000715 int len = strlen(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000716
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000717 int down = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000718 int right = 0;
719 struct filestruct *temp = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000720
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000721 assert(strlenpt(inptr->data) > fill);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000722
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000723 for (i = 0, i_tabs = 0; i < len; i++, i_tabs++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000724 if (!isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000725 last_word_end = current_word_end;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000726
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000727 current_word_start = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000728 current_word_start_t = i_tabs;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000729
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000730 while (!isspace((int) inptr->data[i])
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000731 && inptr->data[i]) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000732 i++;
733 i_tabs++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000734 if (inptr->data[i] < 32)
735 i_tabs++;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000736 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000737
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000738 if (inptr->data[i]) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000739 current_word_end = i;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000740 current_word_end_t = i_tabs;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000741 } else {
742 current_word_end = i - 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000743 current_word_end_t = i_tabs - 1;
744 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000745 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000746
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000747 if (inptr->data[i] == NANO_CONTROL_I) {
Chris Allegretta6d690a32000-08-03 22:51:21 +0000748 if (i_tabs % tabsize != 0);
749 i_tabs += tabsize - (i_tabs % tabsize);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000750 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000751
Adam Rogoyski09f97962000-06-20 02:50:33 +0000752 if (current_word_end_t > fill)
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000753 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +0000754 }
755
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000756 /* There are a few (ever changing) cases of what the line could look like.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000757 * 1) only one word on the line before wrap point.
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000758 * a) one word takes up the whole line with no starting spaces.
759 * - do nothing and return.
760 * b) cursor is on word or before word at wrap point and there are spaces at beginning.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000761 * - word starts new line.
762 * - keep white space on original line up to the cursor.
763 * *) cursor is after word at wrap point
764 * - either it's all white space after word, and this routine isn't called.
765 * - or we are actually in case 2 (2 words).
766 * 2) Two or more words on the line before wrap point.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000767 * a) cursor is at a word or space before wrap point
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000768 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000769 * - white space at end of original line is cleared, unless
770 * it is all spaces between previous word and next word which appears after fill.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000771 * b) cursor is at the word at the wrap point.
772 * - word at wrap point starts a new line.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000773 * 1. pressed a space and at first character of wrap point word.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000774 * - white space on original line is kept to where cursor was.
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000775 * 2. pressed non space (or space elsewhere).
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000776 * - white space at end of original line is cleared.
777 * c) cursor is past the word at the wrap point.
778 * - word at wrap point starts a new line.
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000779 * - white space at end of original line is cleared
780 */
781
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000782 temp = nmalloc(sizeof(filestruct));
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000783
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000784 /* Category 1a: one word taking up the whole line with no beginning spaces. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000785 if ((last_word_end == -1) && (!isspace((int) inptr->data[0]))) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000786 for (i = current_word_end; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000787 if (!isspace((int) inptr->data[i]) && i < len) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000788 current_word_start = i;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000789 while (!isspace((int) inptr->data[i]) && (i < len)) {
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000790 i++;
791 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000792 last_word_end = current_word_end;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000793 current_word_end = i;
794 break;
795 }
796 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000797
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000798 if (last_word_end == -1) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000799 free(temp);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000800 return;
801 }
802 if (current_x >= last_word_end) {
803 right = (current_x - current_word_start) + 1;
804 current_x = last_word_end;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000805 down = 1;
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000806 }
807
808 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
809 strcpy(temp->data, &inptr->data[current_word_start]);
810 inptr->data = nrealloc(inptr->data, last_word_end + 2);
811 inptr->data[last_word_end + 1] = 0;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000812 } else
813 /* Category 1b: one word on the line and word not taking up whole line
814 (i.e. there are spaces at the beginning of the line) */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000815 if (last_word_end == -1) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000816 temp->data = nmalloc(strlen(&inptr->data[current_word_start]) + 1);
817 strcpy(temp->data, &inptr->data[current_word_start]);
818
819 /* Inside word, remove it from original, and move cursor to right spot. */
820 if (current_x >= current_word_start) {
821 right = current_x - current_word_start;
822 current_x = 0;
Chris Allegretta94a78b82001-03-14 08:28:48 +0000823 if (ISSET(AUTOINDENT)) {
824 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000825 while ((inptr->next->data[i] == ' '
826 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +0000827 i++;
828 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000829 }
Chris Allegretta94a78b82001-03-14 08:28:48 +0000830 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000831 down = 1;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000832 }
833
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000834 null_at(inptr->data, current_x);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000835
836 if (ISSET(MARK_ISSET) && (mark_beginbuf == inptr)) {
837 mark_beginbuf = temp;
838 mark_beginx = 0;
839 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000840 }
841
842 /* Category 2: two or more words on the line. */
843 else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000844 /* Case 2a: cursor before word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000845 if (current_x < current_word_start) {
846 temp->data =
847 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
848 strcpy(temp->data, &inptr->data[current_word_start]);
849
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000850 if (!isspace((int) input_char)) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000851 i = current_word_start - 1;
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000852 while (isspace((int) inptr->data[i])) {
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000853 i--;
854 assert(i >= 0);
855 }
856 } else if (current_x <= last_word_end)
857 i = last_word_end - 1;
858 else
859 i = current_x;
860
861 inptr->data = nrealloc(inptr->data, i + 2);
862 inptr->data[i + 1] = 0;
863 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000864
865
866 /* Case 2b: cursor at word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000867 else if ((current_x >= current_word_start)
868 && (current_x <= (current_word_end + 1))) {
869 temp->data =
870 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000871 strcpy(temp->data, &inptr->data[current_word_start]);
872
873 down = 1;
874
875 right = current_x - current_word_start;
Chris Allegretta94a78b82001-03-14 08:28:48 +0000876 if (ISSET(AUTOINDENT)) {
877 int i = 0;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000878 while ((inptr->next->data[i] == ' '
879 || inptr->next->data[i] == '\t')) {
Chris Allegretta94a78b82001-03-14 08:28:48 +0000880 i++;
881 right++;
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000882 }
Chris Allegretta94a78b82001-03-14 08:28:48 +0000883 }
884
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000885 i = current_word_start - 1;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +0000886 if (isspace((int) input_char)
887 && (current_x == current_word_start)) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000888 current_x = current_word_start;
889
Chris Allegretta6925bbd2000-07-28 01:41:29 +0000890 null_at(inptr->data, current_word_start);
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000891 } else {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000892
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000893 while (isspace((int) inptr->data[i])) {
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000894 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000895 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000896 }
897 inptr->data = nrealloc(inptr->data, i + 2);
898 inptr->data[i + 1] = 0;
899 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000900 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000901
902
903 /* Case 2c: cursor past word at wrap point. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000904 else {
905 temp->data =
906 nmalloc(strlen(&inptr->data[current_word_start]) + 1);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000907 strcpy(temp->data, &inptr->data[current_word_start]);
908
909 down = 1;
910 right = current_x - current_word_start;
911
912 current_x = current_word_start;
913 i = current_word_start - 1;
914
Chris Allegretta9e7efa32000-10-02 03:42:55 +0000915 while (isspace((int) inptr->data[i])) {
Adam Rogoyski3d449b42000-06-19 17:30:14 +0000916 i--;
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000917 assert(i >= 0);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000918 inptr->data = nrealloc(inptr->data, i + 2);
919 inptr->data[i + 1] = 0;
920 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000921 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000922 }
923
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000924 /* We pre-pend wrapped part to next line. */
Adam Rogoyski0223d6f2000-06-17 20:36:35 +0000925 if (ISSET(SAMELINEWRAP) && inptr->next) {
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000926 int old_x = current_x, old_y = current_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000927
Chris Allegretta94a78b82001-03-14 08:28:48 +0000928 /* Plus one for the space which concatenates the two lines together plus 1 for \0. */
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000929 char *p =
930 nmalloc((strlen(temp->data) + strlen(inptr->next->data) + 2)
931 * sizeof(char));
Chris Allegretta94a78b82001-03-14 08:28:48 +0000932
933 if (ISSET(AUTOINDENT)) {
934 int non = 0;
935
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000936 /* Grab the beginning of the next line until it's not a
937 space or tab, then null terminate it so we can strcat it
938 to hell */
939 while ((inptr->next->data[non] == ' '
940 || inptr->next->data[non] == '\t'))
941 p[non] = inptr->next->data[non++];
Chris Allegretta94a78b82001-03-14 08:28:48 +0000942
943 p[non] = 0;
944 strcat(p, temp->data);
945 strcat(p, " ");
946
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000947 /* Now tack on the rest of the next line after the spaces and
948 tabs */
Chris Allegretta94a78b82001-03-14 08:28:48 +0000949 strcat(p, &inptr->next->data[non]);
950 } else {
951 strcpy(p, temp->data);
952 strcat(p, " ");
953 strcat(p, inptr->next->data);
954 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000955
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000956 free(inptr->next->data);
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000957 inptr->next->data = p;
958
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000959 free(temp->data);
960 free(temp);
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000961
Adam Rogoyski9aeb9da2000-06-16 01:19:31 +0000962 current_x = old_x;
963 current_y = old_y;
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000964 }
Chris Allegretta4da1fc62000-06-21 03:00:43 +0000965 /* Else we start a new line. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000966 else {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000967
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000968 temp->prev = inptr;
969 temp->next = inptr->next;
970
971 if (inptr->next)
972 inptr->next->prev = temp;
973 inptr->next = temp;
974
975 if (!temp->next)
976 filebot = temp;
977
978 SET(SAMELINEWRAP);
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000979
980 if (ISSET(AUTOINDENT)) {
981 char *spc = inptr->data;
982 char *t = NULL;
983 int extra = 0;
984 if (spc) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +0000985 while ((*spc == ' ') || (*spc == '\t')) {
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000986 extra++;
987 spc++;
Adam Rogoyski1e9183f2001-03-13 18:36:03 +0000988 totsize++;
989 }
990 t = nmalloc(strlen(temp->data) + extra + 1);
991 strncpy(t, inptr->data, extra);
992 strcpy(t + extra, temp->data);
993 free(temp->data);
994 temp->data = t;
995 }
996 }
Adam Rogoyski77f36de2000-06-07 03:56:54 +0000997 }
998
999
1000 totlines++;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001001 /* Everything about it makes me want this line here but it causes
1002 * totsize to be high by one for some reason. Sigh. (Rob) */
1003 /* totsize++; */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001004
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001005 renumber(inptr);
Chris Allegretta234a34d2000-07-29 04:33:38 +00001006 edit_update(edittop, TOP);
Adam Rogoyski0223d6f2000-06-17 20:36:35 +00001007
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001008
1009 /* Move the cursor to the new line if appropriate. */
1010 if (down) {
1011 do_right();
1012 }
1013
1014 /* Move the cursor to the correct spot in the line if appropriate. */
1015 while (right--) {
1016 do_right();
1017 }
1018
Chris Allegretta234a34d2000-07-29 04:33:38 +00001019 edit_update(edittop, TOP);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001020 reset_cursor();
1021 edit_refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001022}
1023
1024/* Check to see if we've just caused the line to wrap to a new line */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001025void check_wrap(filestruct * inptr, char ch)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001026{
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001027 int len = strlenpt(inptr->data);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001028#ifdef DEBUG
1029 fprintf(stderr, _("check_wrap called with inptr->data=\"%s\"\n"),
1030 inptr->data);
1031#endif
1032
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001033 if (len <= fill)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001034 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001035 else {
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001036 int i = actual_x(inptr, fill);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001037
1038 /* Do not wrap if there are no words on or after wrap point. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001039 int char_found = 0;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001040
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001041 while (isspace((int) inptr->data[i]) && inptr->data[i])
Adam Rogoyski09f97962000-06-20 02:50:33 +00001042 i++;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001043
Adam Rogoyski09f97962000-06-20 02:50:33 +00001044 if (!inptr->data[i])
1045 return;
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001046
Adam Rogoyski09f97962000-06-20 02:50:33 +00001047 /* String must be at least 1 character long. */
1048 for (i = strlen(inptr->data) - 1; i >= 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001049 if (isspace((int) inptr->data[i])) {
Adam Rogoyski09f97962000-06-20 02:50:33 +00001050 if (!char_found)
1051 continue;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001052 char_found = 2; /* 2 for yes do wrap. */
Adam Rogoyski09f97962000-06-20 02:50:33 +00001053 break;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001054 } else
1055 char_found = 1; /* 1 for yes found a word, but must check further. */
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001056 }
Adam Rogoyski09f97962000-06-20 02:50:33 +00001057
1058 if (char_found == 2)
1059 do_wrap(inptr, ch);
Adam Rogoyski77f36de2000-06-07 03:56:54 +00001060 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001061}
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001062#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001063
1064/* Stuff we do when we abort from programs and want to clean up the
1065 * screen. This doesnt do much right now.
1066 */
1067void do_early_abort(void)
1068{
1069 blank_statusbar_refresh();
1070}
1071
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001072int do_backspace(void)
1073{
1074 filestruct *previous, *tmp;
1075
1076 if (current_x != 0) {
1077 /* Let's get dangerous */
1078 memmove(&current->data[current_x - 1], &current->data[current_x],
1079 strlen(current->data) - current_x + 1);
1080#ifdef DEBUG
1081 fprintf(stderr, _("current->data now = \"%s\"\n"), current->data);
1082#endif
1083 align(&current->data);
1084 do_left();
1085 } else {
1086 if (current == fileage)
1087 return 0; /* Can't delete past top of file */
1088
1089 previous = current->prev;
1090 current_x = strlen(previous->data);
1091 previous->data = nrealloc(previous->data,
1092 strlen(previous->data) +
1093 strlen(current->data) + 1);
1094 strcat(previous->data, current->data);
1095
1096 tmp = current;
1097 unlink_node(current);
1098 delete_node(current);
1099 if (current == edittop) {
1100 if (previous->next)
1101 current = previous->next;
1102 else
1103 current = previous;
Chris Allegrettada721be2000-07-31 01:26:42 +00001104 page_up_center();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001105 } else {
1106 if (previous->next)
1107 current = previous->next;
1108 else
1109 current = previous;
1110 update_line(current, current_x);
1111 }
1112
1113 /* Ooops, sanity check */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001114 if (tmp == filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001115 filebot = current;
1116 editbot = current;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001117
1118 /* Recreate the magic line if we're deleting it AND if the
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001119 line we're on now is NOT blank. if it is blank we
1120 can just use IT for the magic line. This is how Pico
1121 appears to do it, in any case */
Chris Allegretta28a0f892000-07-05 22:47:54 +00001122 if (strcmp(current->data, "")) {
1123 new_magicline();
1124 fix_editbot();
1125 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001126 }
1127
1128 current = previous;
1129 renumber(current);
1130 previous_line();
1131 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001132#ifdef DEBUG
1133 fprintf(stderr, _("After, data = \"%s\"\n"), current->data);
1134#endif
1135
1136 }
1137
1138 totsize--;
1139 set_modified();
1140 UNSET(KEEP_CUTBUFFER);
1141 edit_refresh();
1142 return 1;
1143}
1144
1145int do_delete(void)
1146{
1147 filestruct *foo;
1148
1149 if (current_x != strlen(current->data)) {
1150 /* Let's get dangerous */
1151 memmove(&current->data[current_x], &current->data[current_x + 1],
1152 strlen(current->data) - current_x);
1153
1154 align(&current->data);
1155
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001156 /* Now that we have a magic lnie again, we can check for both being
1157 on the line before filebot as well as at filebot */
Chris Allegretta4ed13152001-02-10 17:50:50 +00001158 } else if (current->next != NULL && current->next != filebot) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001159 current->data = nrealloc(current->data,
1160 strlen(current->data) +
1161 strlen(current->next->data) + 1);
1162 strcat(current->data, current->next->data);
1163
1164 foo = current->next;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001165 if (filebot == foo) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001166 filebot = current;
1167 editbot = current;
1168 }
1169
1170 unlink_node(foo);
1171 delete_node(foo);
1172 update_line(current, current_x);
1173
Chris Allegretta4ed13152001-02-10 17:50:50 +00001174 /* Please see the comment in do_backspace if you don't understand
Chris Allegretta28a0f892000-07-05 22:47:54 +00001175 this test */
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001176 if (current == filebot && strcmp(current->data, "")) {
Chris Allegretta28a0f892000-07-05 22:47:54 +00001177 new_magicline();
1178 fix_editbot();
Chris Allegretta55373872000-07-06 22:38:37 +00001179 totsize++;
Chris Allegretta28a0f892000-07-05 22:47:54 +00001180 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001181 renumber(current);
1182 totlines--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001183 } else
1184 return 0;
1185
1186 totsize--;
1187 set_modified();
1188 UNSET(KEEP_CUTBUFFER);
1189 edit_refresh();
1190 return 1;
1191}
1192
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001193void wrap_reset(void)
1194{
1195 UNSET(SAMELINEWRAP);
1196}
1197
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001198#ifndef DISABLE_SPELLER
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001199
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001200int do_int_spell_fix(char *word)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001201{
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001202 char *prevanswer = NULL, *save_search = NULL, *save_replace = NULL;
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001203 filestruct *begin;
1204 int i = 0, j = 0, beginx, beginx_top;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001205
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001206 /* save where we are */
1207 begin = current;
1208 beginx = current_x + 1;
1209
1210 /* save the current search/replace strings */
1211 search_init_globals();
1212 save_search = mallocstrcpy(save_search, last_search);
1213 save_replace = mallocstrcpy(save_replace, last_replace);
1214
1215 /* set search/replace strings to mis-spelt word */
1216 prevanswer = mallocstrcpy(prevanswer, word);
1217 last_search = mallocstrcpy(last_search, word);
1218 last_replace = mallocstrcpy(last_replace, word);
1219
1220 /* start from the top of file */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001221 current = fileage;
1222 current_x = beginx_top = -1;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001223
1224 search_last_line = FALSE;
1225
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001226 edit_update(fileage, TOP);
1227
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001228 /* make sure word is still mis-spelt (i.e. when multi-errors) */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001229 if (findnextstr(TRUE, fileage, beginx_top, prevanswer) != NULL) {
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001230 do_replace_highlight(TRUE, prevanswer);
1231
1232 /* allow replace word to be corrected */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001233 i = statusq(0, spell_list, SPELL_LIST_LEN, last_replace,
1234 _("Edit a replacement"));
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001235
1236 do_replace_highlight(FALSE, prevanswer);
1237
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001238 /* start from the start of this line again */
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001239 current = fileage;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001240 current_x = beginx_top;
1241
1242 search_last_line = FALSE;
1243
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001244 j = i;
1245 do_replace_loop(prevanswer, fileage, &beginx_top, TRUE, &j);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001246 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001247
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001248 /* restore the search/replace strings */
1249 last_search = mallocstrcpy(last_search, save_search);
1250 last_replace = mallocstrcpy(last_replace, save_replace);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001251
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001252 /* restore where we were */
1253 current = begin;
1254 current_x = beginx - 1;
1255
1256 edit_update(current, CENTER);
1257
1258 if (i == -1)
1259 return FALSE;
1260
1261 return TRUE;
1262}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001263
1264/* Integrated spell checking using 'spell' program */
Chris Allegretta271e9722000-11-10 18:15:43 +00001265int do_int_speller(char *tempfile_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001266{
Chris Allegretta271e9722000-11-10 18:15:43 +00001267 char *read_buff, *read_buff_ptr, *read_buff_word;
1268 long pipe_buff_size;
1269 int in_fd[2], tempfile_fd;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001270 int spell_status;
1271 pid_t pid_spell;
1272 ssize_t bytesread;
1273
Chris Allegretta271e9722000-11-10 18:15:43 +00001274 /* Create a pipe to spell program */
1275
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001276 if (pipe(in_fd) == -1)
1277 return FALSE;
1278
Chris Allegretta271e9722000-11-10 18:15:43 +00001279 /* A new process to run spell in */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001280
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001281 if ((pid_spell = fork()) == 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001282
1283 /* Child continues, (i.e. future spell process) */
1284
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001285 close(in_fd[0]);
1286
Chris Allegretta271e9722000-11-10 18:15:43 +00001287 /* replace the standard in with the tempfile */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001288
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001289 if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001290
1291 close(in_fd[1]);
1292 exit(1);
1293 }
1294
1295 if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
1296
1297 close(tempfile_fd);
1298 close(in_fd[1]);
1299 exit(1);
1300 }
1301 close(tempfile_fd);
1302
Chris Allegrettad00e6df2000-11-29 04:33:26 +00001303
Chris Allegretta271e9722000-11-10 18:15:43 +00001304 /* send spell's standard out to the pipe */
1305
1306 if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
1307
1308 close(in_fd[1]);
1309 exit(1);
1310 }
1311 close(in_fd[1]);
1312
1313 /* Start spell program, we are using the PATH here!?!? */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001314 execlp("spell", "spell", NULL);
1315
Chris Allegretta271e9722000-11-10 18:15:43 +00001316 /* Should not be reached, if spell is found!!! */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001317
Chris Allegretta271e9722000-11-10 18:15:43 +00001318 exit(1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001319 }
1320
1321 /* Parent continues here */
1322
Chris Allegretta271e9722000-11-10 18:15:43 +00001323 close(in_fd[1]);
1324
1325 /* Child process was not forked successfully */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001326
1327 if (pid_spell < 0) {
1328
Chris Allegretta271e9722000-11-10 18:15:43 +00001329 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001330 return FALSE;
1331 }
1332
Chris Allegretta271e9722000-11-10 18:15:43 +00001333 /* Get system pipe buffer size */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001334
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001335 if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001336
Chris Allegretta271e9722000-11-10 18:15:43 +00001337 close(in_fd[0]);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001338 return FALSE;
Chris Allegretta271e9722000-11-10 18:15:43 +00001339 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001340
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001341 read_buff = nmalloc(pipe_buff_size + 1);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001342
Chris Allegretta271e9722000-11-10 18:15:43 +00001343 /* Process the returned spelling errors */
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001344
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001345 while ((bytesread = read(in_fd[0], read_buff, pipe_buff_size)) > 0) {
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001346
Chris Allegretta271e9722000-11-10 18:15:43 +00001347 read_buff[bytesread] = (char) NULL;
1348 read_buff_word = read_buff_ptr = read_buff;
1349
1350 while (*read_buff_ptr != (char) NULL) {
1351
1352 /* Windows version may need to process additional char '\r' */
1353
1354 /* Possible problem here if last word not followed by '\n' */
1355
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001356 if (*read_buff_ptr == '\n') {
Chris Allegretta271e9722000-11-10 18:15:43 +00001357 *read_buff_ptr = (char) NULL;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001358 if (!do_int_spell_fix(read_buff_word)) {
Chris Allegretta271e9722000-11-10 18:15:43 +00001359
1360 close(in_fd[0]);
1361 free(read_buff);
1362 replace_abort();
1363
1364 return TRUE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001365 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001366 read_buff_word = read_buff_ptr;
1367 read_buff_word++;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001368 }
1369
1370 read_buff_ptr++;
1371 }
1372 }
Chris Allegretta271e9722000-11-10 18:15:43 +00001373
1374 close(in_fd[0]);
1375 free(read_buff);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001376 replace_abort();
1377
Chris Allegretta271e9722000-11-10 18:15:43 +00001378 /* Process end of spell process */
1379
1380 wait(&spell_status);
1381 if (WIFEXITED(spell_status)) {
1382 if (WEXITSTATUS(spell_status) != 0)
1383 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001384 } else
Chris Allegretta271e9722000-11-10 18:15:43 +00001385 return FALSE;
1386
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001387 return TRUE;
1388}
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001389
1390/* External spell checking */
Chris Allegretta271e9722000-11-10 18:15:43 +00001391int do_alt_speller(char *file_name)
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001392{
Chris Allegretta271e9722000-11-10 18:15:43 +00001393 int alt_spell_status;
1394 pid_t pid_spell;
Chris Allegretta169ee842001-01-26 01:57:32 +00001395 char *ptr;
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001396 long lineno_cur = current->lineno;
Chris Allegretta169ee842001-01-26 01:57:32 +00001397 static int arglen = 3;
1398 static char **spellargs = (char **) NULL;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001399
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001400 endwin();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001401
Chris Allegrettae434b452001-01-27 19:25:00 +00001402 /* Set up an argument list to pass the execvp function */
1403 if (spellargs == NULL) {
1404 spellargs = nmalloc(arglen * sizeof(char *));
Chris Allegretta271e9722000-11-10 18:15:43 +00001405
Chris Allegrettae434b452001-01-27 19:25:00 +00001406 spellargs[0] = strtok(alt_speller, " ");
1407 while ((ptr = strtok(NULL, " ")) != NULL) {
1408 arglen++;
1409 spellargs = nrealloc(spellargs, arglen * sizeof(char *));
1410 spellargs[arglen - 3] = ptr;
Chris Allegretta169ee842001-01-26 01:57:32 +00001411 }
Chris Allegrettae434b452001-01-27 19:25:00 +00001412 spellargs[arglen - 1] = NULL;
1413 }
1414 spellargs[arglen - 2] = file_name;
1415
1416 /* Start a new process for the alternate speller */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001417 if ((pid_spell = fork()) == 0) {
Chris Allegretta169ee842001-01-26 01:57:32 +00001418
Chris Allegretta271e9722000-11-10 18:15:43 +00001419 /* Start alternate spell program, we are using the PATH here!?!? */
Chris Allegretta169ee842001-01-26 01:57:32 +00001420 execvp(spellargs[0], spellargs);
Chris Allegretta271e9722000-11-10 18:15:43 +00001421
1422 /* Should not be reached, if alternate speller is found!!! */
1423
1424 exit(1);
1425 }
1426
1427 /* Could not fork?? */
1428
1429 if (pid_spell < 0)
1430 return FALSE;
1431
1432 /* Wait for alternate speller to complete */
1433
1434 wait(&alt_spell_status);
1435 if (WIFEXITED(alt_spell_status)) {
1436 if (WEXITSTATUS(alt_spell_status) != 0)
1437 return FALSE;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001438 } else
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001439 return FALSE;
1440
Chris Allegretta8f6c0692000-07-19 01:16:18 +00001441 refresh();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001442 free_filestruct(fileage);
1443 global_init();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001444 open_file(file_name, 0, 1);
Rocco Corsi4dfaf932001-04-20 01:59:55 +00001445
1446 do_gotoline(lineno_cur);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001447 set_modified();
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001448
1449 return TRUE;
1450}
1451#endif
1452
1453int do_spell(void)
1454{
1455
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001456#ifdef DISABLE_SPELLER
Chris Allegrettaff269f82000-12-01 18:46:01 +00001457 nano_disabled_msg();
1458 return (TRUE);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001459#else
Chris Allegretta271e9722000-11-10 18:15:43 +00001460 char *temp;
1461 int spell_res;
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001462
Chris Allegretta271e9722000-11-10 18:15:43 +00001463 if ((temp = tempnam(0, "nano.")) == NULL) {
1464 statusbar(_("Could not create a temporary filename: %s"),
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001465 strerror(errno));
Chris Allegretta271e9722000-11-10 18:15:43 +00001466 return 0;
1467 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001468
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001469 if (write_file(temp, 1) == -1) {
1470 statusbar(_("Spell checking failed: unable to write temp file!"));
Chris Allegretta271e9722000-11-10 18:15:43 +00001471 return 0;
Chris Allegretta3dbb2782000-12-02 04:36:50 +00001472 }
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001473
Chris Allegretta271e9722000-11-10 18:15:43 +00001474 if (alt_speller)
1475 spell_res = do_alt_speller(temp);
1476 else
1477 spell_res = do_int_speller(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001478
Chris Allegretta271e9722000-11-10 18:15:43 +00001479 remove(temp);
Chris Allegretta27eb13f2000-11-05 16:52:21 +00001480
1481 if (spell_res)
1482 statusbar(_("Finished checking spelling"));
1483 else
1484 statusbar(_("Spell checking failed"));
1485
1486 return spell_res;
1487
Chris Allegrettadbc12b22000-07-03 03:10:14 +00001488#endif
Chris Allegretta67105eb2000-07-03 03:18:32 +00001489}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001490
1491int do_exit(void)
1492{
1493 int i;
1494
1495 if (!ISSET(MODIFIED))
1496 finish(0);
1497
Chris Allegretta30885552000-07-14 01:20:12 +00001498 if (ISSET(TEMP_OPT)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001499 i = 1;
1500 } else {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001501 i = do_yesno(0, 0,
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001502 _
1503 ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
1504 }
1505
1506#ifdef DEBUG
1507 dump_buffer(fileage);
1508#endif
1509
1510 if (i == 1) {
Chris Allegrettae1ebaf32001-01-07 05:50:36 +00001511 if (do_writeout(filename, 1) > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001512 finish(0);
1513 } else if (i == 0)
1514 finish(0);
1515 else
1516 statusbar(_("Cancelled"));
1517
1518 display_main_list();
1519 return 1;
1520}
1521
Chris Allegretta84de5522001-04-12 14:51:48 +00001522#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001523#ifdef NCURSES_MOUSE_VERSION
1524void do_mouse(void)
1525{
1526 MEVENT mevent;
Chris Allegrettae10debd2000-08-22 01:26:42 +00001527 int foo = 0, tab_found = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001528
1529 if (getmouse(&mevent) == ERR)
1530 return;
1531
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001532 /* If mouse not in edit or bottom window, return */
1533 if (wenclose(edit, mevent.y, mevent.x)) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001534
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001535 /* Don't let people screw with the marker when they're in a
1536 subfunction */
1537 if (currshortcut != main_list)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001538 return;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001539
1540 /* Subtract out size of topwin. Perhaps we need a constant somewhere? */
1541 mevent.y -= 2;
1542
1543 /* Selecting where the cursor is sets the mark.
1544 * Selecting beyond the line length with the cursor at the end of the
1545 * line sets the mark as well.
1546 */
1547 if ((mevent.y == current_y) &&
1548 ((mevent.x == current_x) || (current_x == strlen(current->data)
1549 && (mevent.x >
1550 strlen(current->data))))) {
1551 if (ISSET(VIEW_MODE)) {
1552 print_view_warning();
1553 return;
1554 }
1555 do_mark();
1556 } else if (mevent.y > current_y) {
1557 while (mevent.y > current_y) {
1558 if (current->next != NULL)
1559 current = current->next;
1560 else
1561 break;
1562 current_y++;
1563 }
1564 } else if (mevent.y < current_y) {
1565 while (mevent.y < current_y) {
1566 if (current->prev != NULL)
1567 current = current->prev;
1568 else
1569 break;
1570 current_y--;
1571 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001572 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001573 current_x = mevent.x;
1574 placewewant = current_x;
1575 while (foo < current_x) {
1576 if (current->data[foo] == NANO_CONTROL_I) {
1577 current_x -= tabsize - (foo % tabsize);
1578 tab_found = 1;
1579 } else if (current->data[foo] & 0x80);
1580 else if (current->data[foo] < 32)
1581 current_x--;
1582 foo++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001583 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001584 /* This is where tab_found comes in. I can't figure out why,
1585 * but without it any line with a tab will place the cursor
1586 * one character behind. Whatever, this fixes it. */
1587 if (tab_found == 1)
1588 current_x++;
1589
1590 if (current_x > strlen(current->data))
1591 current_x = strlen(current->data);
1592
1593 update_cursor();
1594 edit_refresh();
1595 } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
1596 int k = COLS / 6, val = 0;
1597
1598 /* Determine what shortcut list was clicked */
1599 mevent.y -= (editwinrows + 3);
1600
1601 if (mevent.y < 0) /* They clicked on the statusbar */
1602 return;
1603
1604 /* Don't select stuff beyond list length */
1605 if (mevent.x / k >= currslen)
1606 return;
1607
1608 val = currshortcut[(mevent.x / k) * 2 + mevent.y].val;
1609
1610 /* And ungetch that value */
1611 ungetch(val);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001612 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001613}
1614#endif
1615#endif
1616
1617/* Handler for SIGHUP */
1618RETSIGTYPE handle_hup(int signal)
1619{
Chris Allegrettae7a58932000-12-02 02:36:22 +00001620 die(_("Received SIGHUP"));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001621}
1622
Chris Allegretta18f8be02000-09-04 03:20:38 +00001623/* What do we do when we catch the suspend signal */
1624RETSIGTYPE do_suspend(int signal)
1625{
1626
1627 act.sa_handler = SIG_DFL;
1628 sigemptyset(&act.sa_mask);
1629 sigaction(SIGTSTP, &act, NULL);
1630
1631 endwin();
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001632 fprintf(stderr, "\n\n\n\n\nUse \"fg\" to return to nano\n");
Chris Allegretta18f8be02000-09-04 03:20:38 +00001633 raise(SIGTSTP);
1634}
1635
1636/* Restore the suspend handler when we come back into the prog */
1637RETSIGTYPE do_cont(int signal)
1638{
1639
1640 act.sa_handler = do_suspend;
1641 sigemptyset(&act.sa_mask);
1642 sigaction(SIGTSTP, &act, NULL);
1643 initscr();
1644 total_refresh();
1645}
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001646
1647void handle_sigwinch(int s)
1648{
1649#ifndef NANO_SMALL
1650 char *tty = NULL;
1651 int fd = 0;
1652 int result = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001653 struct winsize win;
1654
1655 tty = ttyname(0);
1656 if (!tty)
1657 return;
1658 fd = open(tty, O_RDWR);
1659 if (fd == -1)
1660 return;
1661 result = ioctl(fd, TIOCGWINSZ, &win);
1662 if (result == -1)
1663 return;
1664
1665
1666 COLS = win.ws_col;
1667 LINES = win.ws_row;
1668
Chris Allegrettae61e8302001-01-14 05:18:27 +00001669 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1670 die_too_small();
1671
1672 if ((fill = COLS - CHARS_FROM_EOL) < MIN_FILL_LENGTH)
1673 die_too_small();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001674
Chris Allegretta0a06e072001-01-23 02:35:04 +00001675 hblank = nrealloc(hblank, COLS + 1);
1676 memset(hblank, ' ', COLS);
1677 hblank[COLS] = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001678
Chris Allegretta618f5d72001-02-16 04:48:30 +00001679#ifdef HAVE_RESIZETERM
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001680 resizeterm(LINES, COLS);
1681#ifdef HAVE_WRESIZE
1682 if (wresize(topwin, 2, COLS) == ERR)
1683 die(_("Cannot resize top win"));
1684 if (mvwin(topwin, 0, 0) == ERR)
1685 die(_("Cannot move top win"));
1686 if (wresize(edit, editwinrows, COLS) == ERR)
1687 die(_("Cannot resize edit win"));
1688 if (mvwin(edit, 2, 0) == ERR)
1689 die(_("Cannot move edit win"));
1690 if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
1691 die(_("Cannot resize bottom win"));
1692 if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
1693 die(_("Cannot move bottom win"));
1694#endif /* HAVE_WRESIZE */
Chris Allegretta618f5d72001-02-16 04:48:30 +00001695#endif /* HAVE_RESIZETERM */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001696
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001697 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001698
Chris Allegrettabceb1b22000-06-19 04:22:15 +00001699 if (current_y > editwinrows - 1) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001700 edit_update(editbot, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001701 }
1702 erase();
Chris Allegretta97accc62000-06-19 05:45:52 +00001703
1704 /* Do these b/c width may have changed... */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001705 refresh();
Chris Allegrettaf4b96012001-01-03 07:11:47 +00001706 titlebar(NULL);
Chris Allegretta97accc62000-06-19 05:45:52 +00001707 edit_refresh();
1708 display_main_list();
Chris Allegretta08020882001-01-29 23:37:54 +00001709 blank_statusbar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001710 total_refresh();
Chris Allegretta08020882001-01-29 23:37:54 +00001711
Chris Allegretta4e90c402001-01-29 23:40:43 +00001712 /* Turn cursor back on for sure */
1713 curs_set(1);
1714
Chris Allegretta08020882001-01-29 23:37:54 +00001715 /* Jump back to mainloop */
1716 siglongjmp(jmpbuf, 1);
1717
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001718#endif
1719}
1720
Chris Allegretta756f2202000-09-01 13:32:47 +00001721void signal_init(void)
1722{
Chris Allegretta756f2202000-09-01 13:32:47 +00001723
1724 /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
1725 memset(&act, 0, sizeof(struct sigaction));
1726 act.sa_handler = SIG_IGN;
1727 sigaction(SIGINT, &act, NULL);
Chris Allegretta756f2202000-09-01 13:32:47 +00001728
Chris Allegretta18f8be02000-09-04 03:20:38 +00001729 if (!ISSET(SUSPEND)) {
Chris Allegretta756f2202000-09-01 13:32:47 +00001730 sigaction(SIGTSTP, &act, NULL);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001731 } else {
Chris Allegretta18f8be02000-09-04 03:20:38 +00001732 act.sa_handler = do_suspend;
1733 sigaction(SIGTSTP, &act, NULL);
1734
1735 act.sa_handler = do_cont;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001736 sigaction(SIGCONT, &act, NULL);
Chris Allegretta18f8be02000-09-04 03:20:38 +00001737 }
1738
Chris Allegretta756f2202000-09-01 13:32:47 +00001739
1740 /* Trap SIGHUP cuz we want to write the file out. */
1741 act.sa_handler = handle_hup;
1742 sigaction(SIGHUP, &act, NULL);
1743
1744 act.sa_handler = handle_sigwinch;
1745 sigaction(SIGWINCH, &act, NULL);
1746
1747}
1748
Chris Allegretta2a42af12000-09-12 23:02:49 +00001749void window_init(void)
1750{
Chris Allegrettae61e8302001-01-14 05:18:27 +00001751 if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
1752 die_too_small();
Chris Allegretta92c9dd22000-09-13 14:03:27 +00001753
Chris Allegretta2a42af12000-09-12 23:02:49 +00001754 /* Setup up the main text window */
1755 edit = newwin(editwinrows, COLS, 2, 0);
1756
1757 /* And the other windows */
1758 topwin = newwin(2, COLS, 0, 0);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001759 bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001760
Chris Allegretta155d6202001-01-08 01:50:37 +00001761#ifdef PDCURSES
1762 /* Oops, I guess we need this again.
1763 Moved here so the keypad still works after a Meta-X, for example */
1764 keypad(edit, TRUE);
1765 keypad(bottomwin, TRUE);
1766#endif
1767
Chris Allegretta2a42af12000-09-12 23:02:49 +00001768}
1769
Chris Allegretta756f2202000-09-01 13:32:47 +00001770void mouse_init(void)
1771{
Chris Allegretta84de5522001-04-12 14:51:48 +00001772#ifndef DISABLE_MOUSE
Chris Allegretta756f2202000-09-01 13:32:47 +00001773#ifdef NCURSES_MOUSE_VERSION
1774 if (ISSET(USE_MOUSE)) {
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001775 keypad_on(edit, 1);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001776 keypad_on(bottomwin, 1);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00001777
Chris Allegretta756f2202000-09-01 13:32:47 +00001778 mousemask(BUTTON1_RELEASED, NULL);
1779 mouseinterval(50);
Chris Allegretta0b88ce02000-09-15 15:46:32 +00001780
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001781 } else
Chris Allegretta756f2202000-09-01 13:32:47 +00001782 mousemask(0, NULL);
Chris Allegretta63c8ab92001-01-04 02:33:52 +00001783
Chris Allegretta756f2202000-09-01 13:32:47 +00001784#endif
1785#endif
1786
1787}
1788
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001789int do_tab(void)
1790{
1791 do_char('\t');
1792 return 1;
1793}
1794
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001795#ifndef DISABLE_JUSTIFY
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001796int empty_line(const char *data)
1797{
1798 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001799 if (!isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001800 return 0;
1801
1802 data++;
1803 }
1804
1805 return 1;
1806}
1807
1808int no_spaces(const char *data)
1809{
1810 while (*data) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001811 if (isspace((int) *data))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001812 return 0;
1813
1814 data++;
1815 }
1816
1817 return 1;
1818}
1819
1820void justify_format(char *data)
1821{
1822 int i = 0;
1823 int len = strlen(data);
1824
1825 /* Skip first character regardless and leading whitespace. */
1826 for (i = 1; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001827 if (!isspace((int) data[i]))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001828 break;
1829 }
1830
1831 i++; /* (i) is now at least 2. */
1832
1833 /* No double spaces allowed unless following a period. Tabs -> space. No double tabs. */
1834 for (; i < len; i++) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001835 if (isspace((int) data[i]) && isspace((int) data[i - 1])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001836 && (data[i - 2] != '.')) {
1837 memmove(data + i, data + i + 1, len - i);
1838 len--;
1839 i--;
1840 }
1841 }
1842}
1843#endif
1844
1845int do_justify(void)
1846{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00001847#ifdef DISABLE_JUSTIFY
Chris Allegrettaff269f82000-12-01 18:46:01 +00001848 nano_disabled_msg();
1849 return 1;
1850#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001851 int slen = 0; /* length of combined lines on one line. */
Chris Allegretta17dcb722001-01-20 21:40:07 +00001852 int initial_y, kbinput = 0, totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00001853 filestruct *initial = NULL, *tmpjust = NULL, *cutbak, *tmptop, *tmpbot;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001854
1855 if (empty_line(current->data)) {
1856 /* Justify starting at first non-empty line. */
1857 do {
1858 if (!current->next)
1859 return 1;
1860
1861 current = current->next;
1862 current_y++;
1863 }
1864 while (empty_line(current->data));
1865 } else {
1866 /* Search back for the beginning of the paragraph, where
1867 * Paragraph is 1) A line with leading whitespace
1868 * or 2) A line following an empty line.
1869 */
1870 while (current->prev != NULL) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001871 if (isspace((int) current->data[0]) || !current->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001872 break;
1873
1874 current = current->prev;
1875 current_y--;
1876 }
1877
1878 /* First line with leading whitespace may be empty. */
1879 if (empty_line(current->data)) {
1880 if (current->next) {
1881 current = current->next;
1882 current_y++;
1883 } else
1884 return 1;
1885 }
1886 }
1887 initial = current;
1888 initial_y = current_y;
1889
1890 set_modified();
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001891 cutbak = cutbuffer; /* Got to like cutbak ;) */
Chris Allegretta17dcb722001-01-20 21:40:07 +00001892 totbak = totsize;
Chris Allegretta9149e612000-11-27 00:23:41 +00001893 cutbuffer = NULL;
1894
1895 tmptop = current;
1896 tmpjust = copy_node(current);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001897
1898 /* This is annoying because it mucks with totsize */
Chris Allegretta9149e612000-11-27 00:23:41 +00001899 add_to_cutbuffer(tmpjust);
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001900
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001901 /* Put the whole paragraph into one big line. */
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001902 while (current->next && !isspace((int) current->next->data[0])
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001903 && current->next->data[0]) {
1904 filestruct *tmpnode = current->next;
1905 int len = strlen(current->data);
1906 int len2 = strlen(current->next->data);
1907
Chris Allegretta9149e612000-11-27 00:23:41 +00001908 tmpjust = NULL;
Chris Allegretta9149e612000-11-27 00:23:41 +00001909 tmpjust = copy_node(current->next);
1910 add_to_cutbuffer(tmpjust);
1911
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001912 /* Wiping out a newline */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001913 totsize--;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001914
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001915 /* length of both strings plus space between strings and ending \0. */
1916 current->data = nrealloc(current->data, len + len2 + 2);
1917 current->data[len++] = ' ';
1918 current->data[len] = '\0';
1919
1920 strncat(current->data, current->next->data, len2);
1921
1922 unlink_node(tmpnode);
1923 delete_node(tmpnode);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001924 }
1925
1926 justify_format(current->data);
1927
1928 slen = strlen(current->data);
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001929 totsize += slen;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001930
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001931 if ((strlenpt(current->data) > (fill))
1932 && !no_spaces(current->data)) {
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001933 do {
1934 int i = 0;
1935 int len2 = 0;
1936 filestruct *tmpline = nmalloc(sizeof(filestruct));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001937
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001938 /* Start at fill , unless line isn't that long (but it
1939 * appears at least fill long with tabs.
1940 */
1941 if (slen > fill)
1942 i = fill;
1943 else
1944 i = slen;
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001945
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001946 for (; i > 0; i--) {
Chris Allegretta9e7efa32000-10-02 03:42:55 +00001947 if (isspace((int) current->data[i]) &&
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001948 ((strlenpt(current->data) - strlen(current->data + i))
1949 <= fill))
1950 break;
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001951 }
Robert Siemborski60cd6aa2001-01-21 23:23:48 +00001952
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001953 if (!i)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001954 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001955
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001956 current->data[i] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001957
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001958 len2 = strlen(current->data + i + 1);
1959 tmpline->data = nmalloc(len2 + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001960
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001961 /* Skip the white space in current. */
1962 memcpy(tmpline->data, current->data + i + 1, len2);
1963 tmpline->data[len2] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001964
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001965 current->data = nrealloc(current->data, i + 1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001966
Robert Siemborskia417ddc2000-07-24 23:18:48 +00001967 tmpline->prev = current;
1968 tmpline->next = current->next;
1969 if (current->next != NULL)
1970 current->next->prev = tmpline;
1971
1972 current->next = tmpline;
1973 current = tmpline;
1974 slen -= i + 1;
1975 current_y++;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00001976 } while ((strlenpt(current->data) > (fill))
1977 && !no_spaces(current->data));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001978 }
Chris Allegretta9149e612000-11-27 00:23:41 +00001979 tmpbot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001980
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001981 if (current->next)
1982 current = current->next;
Adam Rogoyski09f97962000-06-20 02:50:33 +00001983 else
1984 filebot = current;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001985 current_x = 0;
1986 placewewant = 0;
1987
Adam Rogoyski09f97962000-06-20 02:50:33 +00001988 renumber(initial);
1989 totlines = filebot->lineno;
1990
1991 werase(edit);
1992
Chris Allegretta4da1fc62000-06-21 03:00:43 +00001993 if ((current_y < 0) || (current_y >= editwinrows - 1)
1994 || (initial_y <= 0)) {
Chris Allegretta234a34d2000-07-29 04:33:38 +00001995 edit_update(current, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001996 center_cursor();
1997 } else {
Robert Siemborskidd53ec22000-07-04 02:35:19 +00001998 fix_editbot();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001999 }
2000
Adam Rogoyski09f97962000-06-20 02:50:33 +00002001 edit_refresh();
Chris Allegretta9149e612000-11-27 00:23:41 +00002002 statusbar(_("Can now UnJustify!"));
Chris Allegretta07798352000-11-27 22:58:23 +00002003 /* Change the shortcut list to display the unjustify code */
2004 shortcut_init(1);
2005 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002006 reset_cursor();
2007
Chris Allegretta07798352000-11-27 22:58:23 +00002008 /* Now get a keystroke and see if it's unjustify, if not unget the keytroke
Chris Allegretta9149e612000-11-27 00:23:41 +00002009 and return */
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002010 if ((kbinput = wgetch(edit)) != NANO_UNJUSTIFY_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002011 ungetch(kbinput);
Chris Allegretta00ae5df2001-02-05 18:24:33 +00002012 blank_statusbar_refresh();
2013 } else {
Chris Allegretta9149e612000-11-27 00:23:41 +00002014 /* Else restore the justify we just did (ungrateful user!) */
2015 if (tmptop->prev != NULL)
2016 tmptop->prev->next = tmpbot->next;
Chris Allegrettad022eac2000-11-27 02:50:49 +00002017 else
2018 fileage = current;
Chris Allegretta9149e612000-11-27 00:23:41 +00002019 tmpbot->next->prev = tmptop->prev;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002020 current = tmpbot->next;
Chris Allegretta9149e612000-11-27 00:23:41 +00002021 tmpbot->next = NULL;
2022 do_uncut_text();
Chris Allegrettad022eac2000-11-27 02:50:49 +00002023 if (tmptop->prev == NULL)
2024 edit_refresh();
2025
Chris Allegretta17dcb722001-01-20 21:40:07 +00002026 /* Restore totsize from befure justify */
2027 totsize = totbak;
Chris Allegretta9149e612000-11-27 00:23:41 +00002028 free_filestruct(tmptop);
2029 blank_statusbar_refresh();
2030 }
Chris Allegretta4a9c8582000-11-27 22:59:40 +00002031 shortcut_init(0);
2032 display_main_list();
Chris Allegretta9149e612000-11-27 00:23:41 +00002033 free_filestruct(cutbuffer);
2034 cutbuffer = cutbak;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002035
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002036 return 1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002037#endif
2038}
2039
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002040#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002041void help_init(void)
2042{
2043 int i, sofar = 0;
2044 long allocsize = 1; /* How much space we're gonna need for the help text */
Chris Allegretta220ba692000-12-18 03:40:00 +00002045 char buf[BUFSIZ] = "";
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002046
2047 /* Compute the space needed for the shortcut lists - we add 15 to
2048 have room for the shortcut abbrev and its possible alternate keys */
Chris Allegretta220ba692000-12-18 03:40:00 +00002049 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002050 if (main_list[i].help != NULL)
2051 allocsize += strlen(main_list[i].help) + 15;
2052
Chris Allegretta756f2202000-09-01 13:32:47 +00002053 /* And for the toggle list, we also allocate space for extra text. */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00002054 for (i = 0; i <= TOGGLE_LEN - 1; i++)
Chris Allegretta756f2202000-09-01 13:32:47 +00002055 if (toggles[i].desc != NULL)
2056 allocsize += strlen(toggles[i].desc) + 30;
2057
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002058 allocsize += strlen(help_text_init);
2059
2060 if (help_text != NULL)
2061 free(help_text);
2062
2063 /* Allocate space for the help text */
2064 help_text = nmalloc(allocsize);
2065
2066 /* Now add the text we want */
2067 strcpy(help_text, help_text_init);
2068
2069 /* Now add our shortcut info */
Chris Allegretta220ba692000-12-18 03:40:00 +00002070 for (i = 0; i <= MAIN_LIST_LEN - 1; i++) {
Robert Siemborski6af14312000-07-01 21:34:26 +00002071 sofar = snprintf(buf, BUFSIZ, "^%c ", main_list[i].val + 64);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002072
2073 if (main_list[i].misc1 > KEY_F0 && main_list[i].misc1 <= KEY_F(64))
Robert Siemborski6af14312000-07-01 21:34:26 +00002074 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(F%d) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002075 main_list[i].misc1 - KEY_F0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002076 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002077 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002078
2079 if (main_list[i].altval > 0)
Chris Allegrettae49f1232000-09-02 07:20:39 +00002080 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, "(M-%c) ",
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002081 main_list[i].altval - 32);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002082 else
Robert Siemborski6af14312000-07-01 21:34:26 +00002083 sofar += snprintf(&buf[sofar], BUFSIZ - sofar, " ");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002084
Chris Allegretta756f2202000-09-01 13:32:47 +00002085
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002086 if (main_list[i].help != NULL)
Robert Siemborski976847c2000-07-06 03:43:05 +00002087 snprintf(&buf[sofar], BUFSIZ - sofar, "%s", main_list[i].help);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002088
Chris Allegretta756f2202000-09-01 13:32:47 +00002089
2090 strcat(help_text, buf);
2091 strcat(help_text, "\n");
2092 }
2093
2094 /* And the toggles... */
Chris Allegretta423cbfd2000-09-04 16:21:29 +00002095 for (i = 0; i <= TOGGLE_LEN - 1; i++) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002096 sofar = snprintf(buf, BUFSIZ,
2097 "M-%c ", toggles[i].val - 32);
Chris Allegretta756f2202000-09-01 13:32:47 +00002098
2099 if (toggles[i].desc != NULL)
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002100 snprintf(&buf[sofar], BUFSIZ - sofar, _("%s enable/disable"),
2101 toggles[i].desc);
Chris Allegretta756f2202000-09-01 13:32:47 +00002102
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002103 strcat(help_text, buf);
Robert Siemborski976847c2000-07-06 03:43:05 +00002104 strcat(help_text, "\n");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002105 }
2106
2107}
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002108#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002109
Chris Allegretta756f2202000-09-01 13:32:47 +00002110void do_toggle(int which)
2111{
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002112#ifdef NANO_SMALL
2113 nano_disabled_msg();
2114#else
Jordi Mallach2dc0f6b2000-09-07 10:48:00 +00002115 char *enabled = _("enabled");
2116 char *disabled = _("disabled");
Chris Allegrettaf0f63a82000-09-02 18:44:21 +00002117
Chris Allegretta2a42af12000-09-12 23:02:49 +00002118 if (ISSET(toggles[which].flag))
Chris Allegretta756f2202000-09-01 13:32:47 +00002119 UNSET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002120 else
Chris Allegretta756f2202000-09-01 13:32:47 +00002121 SET(toggles[which].flag);
Chris Allegretta2a42af12000-09-12 23:02:49 +00002122
Chris Allegretta756f2202000-09-01 13:32:47 +00002123 switch (toggles[which].val) {
2124 case TOGGLE_PICOMODE_KEY:
Chris Allegretta07798352000-11-27 22:58:23 +00002125 shortcut_init(0);
Chris Allegretta756f2202000-09-01 13:32:47 +00002126 display_main_list();
2127 break;
2128 case TOGGLE_SUSPEND_KEY:
2129 signal_init();
2130 break;
2131 case TOGGLE_MOUSE_KEY:
2132 mouse_init();
2133 break;
2134 case TOGGLE_NOHELP_KEY:
Chris Allegretta2a42af12000-09-12 23:02:49 +00002135 wclear(bottomwin);
2136 wrefresh(bottomwin);
2137 window_init();
Chris Allegrettaaffeda82000-12-18 04:03:48 +00002138 fix_editbot();
Chris Allegretta2a42af12000-09-12 23:02:49 +00002139 edit_refresh();
2140 display_main_list();
Chris Allegretta756f2202000-09-01 13:32:47 +00002141 break;
2142 }
Chris Allegretta2a42af12000-09-12 23:02:49 +00002143
2144 if (!ISSET(toggles[which].flag)) {
2145 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002146 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002147 statusbar("%s %s", toggles[which].desc, enabled);
2148 else
2149 statusbar("%s %s", toggles[which].desc, disabled);
2150 } else {
2151 if (toggles[which].val == TOGGLE_NOHELP_KEY ||
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002152 toggles[which].val == TOGGLE_WRAP_KEY)
Chris Allegretta2a42af12000-09-12 23:02:49 +00002153 statusbar("%s %s", toggles[which].desc, disabled);
2154 else
2155 statusbar("%s %s", toggles[which].desc, enabled);
2156 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002157 SET(DISABLE_CURPOS);
2158
2159#endif
2160}
2161
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002162/* If the NumLock key has made the keypad gone awry, print an error
2163 message, hopefully we can address it later. */
2164void print_numlock_warning(void)
2165{
2166 static int didmsg = 0;
2167 if (!didmsg) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002168 statusbar(_
2169 ("NumLock glitch detected. Keypad will malfunction with NumLock off"));
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002170 didmsg = 1;
2171 }
2172}
2173
Chris Allegretta1748cd12001-01-13 17:22:54 +00002174/* This function returns the correct keystroke, given the A,B,C or D
2175 input key. This is a common sequence of many terms which send
2176 Esc-O-[A-D] or Esc-[-[A-D]. */
2177int ABCD(int input)
2178{
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002179 switch (input) {
2180 case 'A':
2181 return (KEY_UP);
2182 case 'B':
2183 return (KEY_DOWN);
2184 case 'C':
2185 return (KEY_RIGHT);
2186 case 'D':
2187 return (KEY_LEFT);
2188 default:
2189 return 0;
Chris Allegretta1748cd12001-01-13 17:22:54 +00002190 }
2191}
2192
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002193int main(int argc, char *argv[])
2194{
2195 int optchr;
2196 int kbinput; /* Input from keyboard */
2197 long startline = 0; /* Line to try and start at */
Chris Allegretta08020882001-01-29 23:37:54 +00002198 int keyhandled; /* Have we handled the keystroke yet? */
2199 int i, modify_control_seq;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002200 char *argv0;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002201#ifdef _POSIX_VDISABLE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002202 struct termios term;
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002203#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002204
2205#ifdef HAVE_GETOPT_LONG
2206 int option_index = 0;
2207 struct option long_options[] = {
Chris Allegretta805c26d2000-09-06 13:39:17 +00002208#ifdef HAVE_REGEX_H
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002209 {"regexp", 0, 0, 'R'},
Chris Allegretta47805612000-07-07 02:35:34 +00002210#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002211 {"version", 0, 0, 'V'},
2212 {"const", 0, 0, 'c'},
2213 {"suspend", 0, 0, 'z'},
2214 {"nowrap", 0, 0, 'w'},
2215 {"nohelp", 0, 0, 'x'},
2216 {"help", 0, 0, 'h'},
Chris Allegretta7492cec2000-12-18 04:55:21 +00002217 {"view", 0, 0, 'v'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002218#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002219 {"cut", 0, 0, 'k'},
Chris Allegrettad19e9912000-07-12 18:14:51 +00002220#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002221 {"autoindent", 0, 0, 'i'},
2222 {"tempfile", 0, 0, 't'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002223#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002224 {"speller", 1, 0, 's'},
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002225#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002226 {"fill", 1, 0, 'r'},
2227 {"mouse", 0, 0, 'm'},
2228 {"pico", 0, 0, 'p'},
2229 {"nofollow", 0, 0, 'l'},
Chris Allegretta4dbcc3c2000-08-04 15:44:29 +00002230 {"tabsize", 1, 0, 'T'},
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002231 {0, 0, 0, 0}
2232 };
2233#endif
2234
2235 /* Flag inits... */
2236 SET(FOLLOW_SYMLINKS);
2237
2238#ifndef NANO_SMALL
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002239#ifdef ENABLE_NLS
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002240 setlocale(LC_ALL, "");
2241 bindtextdomain(PACKAGE, LOCALEDIR);
2242 textdomain(PACKAGE);
2243#endif
Chris Allegretta8bc03b62001-02-09 02:57:52 +00002244#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002245
Chris Allegretta8d8e0122001-04-18 04:28:54 +00002246#ifdef ENABLE_NANORC
2247 do_rcfile();
2248#endif /* ENABLE_NANORC */
2249
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002250#ifdef HAVE_GETOPT_LONG
Rocco Corsi12f294c2001-04-14 06:50:24 +00002251 while ((optchr = getopt_long(argc, argv, "?T:RVbcefghijklmpr:s:tvwxz",
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002252 long_options, &option_index)) != EOF) {
2253#else
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002254 while ((optchr =
Rocco Corsi12f294c2001-04-14 06:50:24 +00002255 getopt(argc, argv, "h?T:RVbcefgijklmpr:s:tvwxz")) != EOF) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002256#endif
2257
2258 switch (optchr) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002259 case 'T':
Chris Allegretta99bf73f2000-08-04 00:22:08 +00002260 tabsize = atoi(optarg);
2261 if (tabsize <= 0) {
Chris Allegretta6724a7e2000-06-19 23:19:07 +00002262 usage(); /* To stop bogus data for tab width */
2263 finish(1);
2264 }
2265 break;
Chris Allegretta805c26d2000-09-06 13:39:17 +00002266#ifdef HAVE_REGEX_H
Chris Allegretta9fc8d432000-07-07 01:49:52 +00002267 case 'R':
2268 SET(USE_REGEXP);
2269 break;
Chris Allegretta47805612000-07-07 02:35:34 +00002270#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002271 case 'V':
2272 version();
2273 exit(0);
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002274 case 'b':
2275 case 'e':
2276 case 'f':
Rocco Corsi12f294c2001-04-14 06:50:24 +00002277 case 'g':
2278 case 'j':
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002279 /* Pico compatibility flags */
2280 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002281 case 'c':
2282 SET(CONSTUPDATE);
2283 break;
2284 case 'h':
2285 case '?':
2286 usage();
2287 exit(0);
2288 case 'i':
2289 SET(AUTOINDENT);
2290 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002291#ifndef NANO_SMALL
Chris Allegretta627de192000-07-12 02:09:17 +00002292 case 'k':
2293 SET(CUT_TO_END);
2294 break;
Chris Allegrettad19e9912000-07-12 18:14:51 +00002295#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002296 case 'l':
2297 UNSET(FOLLOW_SYMLINKS);
2298 break;
2299 case 'm':
2300 SET(USE_MOUSE);
2301 break;
2302 case 'p':
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002303 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002304 break;
2305 case 'r':
2306 fill = atoi(optarg);
2307 if (fill <= 0) {
2308 usage(); /* To stop bogus data (like a string) */
2309 finish(1);
2310 }
2311 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002312#ifndef DISABLE_SPELLER
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002313 case 's':
2314 alt_speller = nmalloc(strlen(optarg) + 1);
2315 strcpy(alt_speller, optarg);
2316 break;
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002317#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002318 case 't':
Chris Allegretta30885552000-07-14 01:20:12 +00002319 SET(TEMP_OPT);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002320 break;
2321 case 'v':
2322 SET(VIEW_MODE);
2323 break;
2324 case 'w':
Chris Allegrettacef7fbb2001-04-02 05:36:08 +00002325#ifdef DISABLE_WRAPPING
2326 usage();
2327 exit(0);
2328#else
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002329 SET(NO_WRAP);
2330 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002331#endif /* DISABLE_WRAPPING */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002332 case 'x':
2333 SET(NO_HELP);
2334 break;
2335 case 'z':
2336 SET(SUSPEND);
2337 break;
2338 default:
2339 usage();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002340 exit(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002341 }
2342
2343 }
2344
2345 argv0 = strrchr(argv[0], '/');
2346 if ((argv0 && strstr(argv0, "pico"))
2347 || (!argv0 && strstr(argv[0], "pico")))
Chris Allegrettabf9a8cc2000-11-17 01:37:39 +00002348 SET(PICO_MODE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002349
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002350 /* See if there's a non-option in argv (first non-option is the
2351 filename, if +LINE is not given) */
2352 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002353 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002354 else {
2355 /* Look for the +line flag... */
2356 if (argv[optind][0] == '+') {
2357 startline = atoi(&argv[optind][1]);
2358 optind++;
2359 if (argc == 1 || argc <= optind)
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002360 clear_filename();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002361 else
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002362 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002363
Chris Allegretta1a6e9042000-12-14 13:56:28 +00002364 } else
2365 filename = mallocstrcpy(filename, argv[optind]);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002366 }
2367
2368
2369 /* First back up the old settings so they can be restored, duh */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002370 tcgetattr(0, &oldterm);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002371
Chris Allegretta9239d742000-09-06 15:19:18 +00002372#ifdef _POSIX_VDISABLE
Chris Allegretta8f6c0692000-07-19 01:16:18 +00002373 term = oldterm;
2374 term.c_cc[VINTR] = _POSIX_VDISABLE;
2375 term.c_cc[VQUIT] = _POSIX_VDISABLE;
2376 term.c_lflag &= ~IEXTEN;
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002377 tcsetattr(0, TCSANOW, &term);
Chris Allegretta9239d742000-09-06 15:19:18 +00002378#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002379
2380 /* now ncurses init stuff... */
2381 initscr();
2382 savetty();
2383 nonl();
2384 cbreak();
2385 noecho();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002386
2387 /* Set up some global variables */
2388 global_init();
Chris Allegretta07798352000-11-27 22:58:23 +00002389 shortcut_init(0);
Rocco Corsiaf5c3022001-01-12 07:51:05 +00002390#ifndef DISABLE_HELP
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002391 init_help_msg();
2392 help_init();
Chris Allegretta3bc8c722000-12-10 17:03:25 +00002393#endif
Chris Allegretta756f2202000-09-01 13:32:47 +00002394 signal_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002395
2396#ifdef DEBUG
2397 fprintf(stderr, _("Main: set up windows\n"));
2398#endif
2399
Chris Allegretta2a42af12000-09-12 23:02:49 +00002400 window_init();
Chris Allegretta756f2202000-09-01 13:32:47 +00002401 mouse_init();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002402
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002403#ifdef DEBUG
2404 fprintf(stderr, _("Main: bottom win\n"));
2405#endif
2406 /* Set up up bottom of window */
2407 display_main_list();
2408
2409#ifdef DEBUG
2410 fprintf(stderr, _("Main: open file\n"));
2411#endif
2412
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002413 titlebar(NULL);
Chris Allegretta31c76662000-11-21 06:20:20 +00002414
2415 /* Now we check to see if argv[optind] is non-null to determine if
2416 we're dealing with a new file or not, not argc == 1... */
2417 if (argv[optind] == NULL)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002418 new_file();
2419 else
2420 open_file(filename, 0, 0);
2421
2422 if (startline > 0)
2423 do_gotoline(startline);
2424 else
Chris Allegretta234a34d2000-07-29 04:33:38 +00002425 edit_update(fileage, CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002426
Chris Allegretta08020882001-01-29 23:37:54 +00002427 /* return here after a sigwinch */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002428 sigsetjmp(jmpbuf, 1);
Chris Allegretta08020882001-01-29 23:37:54 +00002429
2430 /* Fix clobber-age */
2431 kbinput = 0;
2432 keyhandled = 0;
2433 modify_control_seq = 0;
2434
Robert Siemborski6967eec2000-07-08 14:23:32 +00002435 edit_refresh();
2436 reset_cursor();
2437
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002438 while (1) {
Chris Allegretta9239d742000-09-06 15:19:18 +00002439
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002440 currshortcut = main_list;
2441 currslen = MAIN_VISIBLE;
2442
Chris Allegretta9239d742000-09-06 15:19:18 +00002443#ifndef _POSIX_VDISABLE
2444 /* We're going to have to do it the old way, i.e. on cygwin */
2445 raw();
2446#endif
2447
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002448 kbinput = wgetch(edit);
Chris Allegrettac08f50d2001-01-06 18:12:43 +00002449#ifdef DEBUG
2450 fprintf(stderr, "AHA! %c (%d)\n", kbinput, kbinput);
2451#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002452 if (kbinput == 27) { /* Grab Alt-key stuff first */
2453 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002454 /* Alt-O, suddenly very important ;) */
Chris Allegretta16e41682000-09-11 22:33:54 +00002455 case 79:
2456 kbinput = wgetch(edit);
Chris Allegretta1748cd12001-01-13 17:22:54 +00002457 if (kbinput <= 'D' && kbinput >= 'A')
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002458 kbinput = ABCD(kbinput);
Chris Allegretta201d9bf2001-01-14 03:17:53 +00002459 else if (kbinput <= 'z' && kbinput >= 'j')
2460 print_numlock_warning();
2461 else if (kbinput <= 'S' && kbinput >= 'P')
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002462 kbinput = KEY_F(kbinput - 79);
Chris Allegretta16e41682000-09-11 22:33:54 +00002463#ifdef DEBUG
2464 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002465 fprintf(stderr, _("I got Alt-O-%c! (%d)\n"),
2466 kbinput, kbinput);
2467 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002468 }
2469#endif
2470 break;
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002471 case 27:
2472 /* If we get Alt-Alt, the next keystroke should be the same as a
2473 control sequence */
2474 modify_control_seq = 1;
2475 keyhandled = 1;
2476 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002477 case 91:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002478 switch (kbinput = wgetch(edit)) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002479 case '1': /* Alt-[-1-[0-5,7-9] = F1-F8 in X at least */
Chris Allegretta16e41682000-09-11 22:33:54 +00002480 kbinput = wgetch(edit);
2481 if (kbinput >= '1' && kbinput <= '5') {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002482 kbinput = KEY_F(kbinput - 48);
2483 wgetch(edit);
2484 } else if (kbinput >= '7' && kbinput <= '9') {
2485 kbinput = KEY_F(kbinput - 49);
2486 wgetch(edit);
2487 } else if (kbinput == 126)
2488 kbinput = KEY_HOME;
Chris Allegretta16e41682000-09-11 22:33:54 +00002489
2490#ifdef DEBUG
2491 else {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002492 fprintf(stderr, _("I got Alt-[-1-%c! (%d)\n"),
2493 kbinput, kbinput);
2494 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002495 }
2496#endif
2497
2498 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002499 case '2': /* Alt-[-2-[0,1,3,4] = F9-F12 in many terms */
Chris Allegretta16e41682000-09-11 22:33:54 +00002500 kbinput = wgetch(edit);
Chris Allegretta16e41682000-09-11 22:33:54 +00002501 switch (kbinput) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002502 case '0':
2503 kbinput = KEY_F(9);
2504 wgetch(edit);
2505 break;
2506 case '1':
2507 kbinput = KEY_F(10);
2508 wgetch(edit);
2509 break;
2510 case '3':
2511 kbinput = KEY_F(11);
2512 wgetch(edit);
2513 break;
2514 case '4':
2515 kbinput = KEY_F(12);
2516 wgetch(edit);
2517 break;
2518 case 126: /* Hack, make insert key do something
2519 usefile, like insert file */
2520 do_insertfile();
2521 keyhandled = 1;
2522 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002523#ifdef DEBUG
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002524 default:
2525 fprintf(stderr, _("I got Alt-[-2-%c! (%d)\n"),
2526 kbinput, kbinput);
2527 break;
Chris Allegretta16e41682000-09-11 22:33:54 +00002528#endif
2529
2530 }
2531 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002532 case '3': /* Alt-[-3 = Delete? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002533 kbinput = NANO_DELETE_KEY;
2534 wgetch(edit);
2535 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002536 case '4': /* Alt-[-4 = End? */
Chris Allegretta16e41682000-09-11 22:33:54 +00002537 kbinput = NANO_END_KEY;
2538 wgetch(edit);
2539 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002540 case '5': /* Alt-[-5 = Page Up */
Chris Allegretta16e41682000-09-11 22:33:54 +00002541 kbinput = KEY_PPAGE;
2542 wgetch(edit);
2543 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002544 case '6': /* Alt-[-6 = Page Down */
Chris Allegretta16e41682000-09-11 22:33:54 +00002545 kbinput = KEY_NPAGE;
2546 wgetch(edit);
2547 break;
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002548 case '[': /* Alt-[-[-[A-E], F1-F5 in linux console */
Chris Allegretta16e41682000-09-11 22:33:54 +00002549 kbinput = wgetch(edit);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002550 if (kbinput >= 'A' && kbinput <= 'E')
2551 kbinput = KEY_F(kbinput - 64);
Chris Allegretta16e41682000-09-11 22:33:54 +00002552 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002553 case 'A':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002554 case 'B':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002555 case 'C':
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002556 case 'D':
Chris Allegretta1748cd12001-01-13 17:22:54 +00002557 kbinput = ABCD(kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002558 break;
2559 case 'H':
2560 kbinput = KEY_HOME;
2561 break;
2562 case 'F':
2563 kbinput = KEY_END;
2564 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002565 default:
2566#ifdef DEBUG
2567 fprintf(stderr, _("I got Alt-[-%c! (%d)\n"),
2568 kbinput, kbinput);
2569#endif
2570 break;
2571 }
2572 break;
2573 default:
2574
2575 /* Check for the altkey defs.... */
2576 for (i = 0; i <= MAIN_LIST_LEN - 1; i++)
2577 if (kbinput == main_list[i].altval ||
2578 kbinput == main_list[i].altval - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002579 kbinput = main_list[i].val;
2580 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002581 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002582#ifndef NANO_SMALL
2583 /* And for toggle switches */
2584 for (i = 0; i <= TOGGLE_LEN - 1 && !keyhandled; i++)
2585 if (kbinput == toggles[i].val ||
2586 kbinput == toggles[i].val - 32) {
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002587 do_toggle(i);
2588 keyhandled = 1;
2589 break;
Chris Allegretta756f2202000-09-01 13:32:47 +00002590 }
2591#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002592#ifdef DEBUG
2593 fprintf(stderr, _("I got Alt-%c! (%d)\n"), kbinput,
2594 kbinput);
2595#endif
2596 break;
2597 }
2598 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002599 /* If the modify_control_seq is set, we received an Alt-Alt
2600 sequence before this, so we make this key a control sequence
2601 by subtracting 64 or 96, depending on its value. */
2602 if (!keyhandled && modify_control_seq) {
2603 if (kbinput >= 'A' && kbinput < 'a')
2604 kbinput -= 64;
2605 else if (kbinput >= 'a' && kbinput <= 'z')
2606 kbinput -= 96;
2607
2608 modify_control_seq = 0;
2609 }
2610
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002611 /* Look through the main shortcut list to see if we've hit a
2612 shortcut key */
Chris Allegretta756f2202000-09-01 13:32:47 +00002613 for (i = 0; i < MAIN_LIST_LEN && !keyhandled; i++) {
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002614 if (kbinput == main_list[i].val ||
2615 (main_list[i].misc1 && kbinput == main_list[i].misc1) ||
2616 (main_list[i].misc2 && kbinput == main_list[i].misc2)) {
2617 if (ISSET(VIEW_MODE) && !main_list[i].viewok)
2618 print_view_warning();
2619 else
2620 main_list[i].func();
2621 keyhandled = 1;
2622 }
2623 }
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002624 /* If we're in raw mode or using Alt-Alt-x, we have to catch
2625 Control-S and Control-Q */
Chris Allegretta9239d742000-09-06 15:19:18 +00002626 if (kbinput == 17 || kbinput == 19)
2627 keyhandled = 1;
2628
Chris Allegretta51b3eec2000-12-18 02:23:50 +00002629 /* Catch ^Z by hand when triggered also */
Chris Allegretta9239d742000-09-06 15:19:18 +00002630 if (kbinput == 26) {
2631 if (ISSET(SUSPEND))
2632 do_suspend(0);
2633 keyhandled = 1;
2634 }
Chris Allegretta9239d742000-09-06 15:19:18 +00002635
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002636 /* Last gasp, stuff that's not in the main lists */
2637 if (!keyhandled)
2638 switch (kbinput) {
Chris Allegretta84de5522001-04-12 14:51:48 +00002639#ifndef DISABLE_MOUSE
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002640#ifdef NCURSES_MOUSE_VERSION
2641 case KEY_MOUSE:
2642 do_mouse();
2643 break;
2644#endif
2645#endif
2646 case 0: /* Erg */
2647 do_next_word();
2648 break;
Chris Allegrettaf4f7e042001-01-04 16:56:15 +00002649
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002650 case 331: /* Stuff that we don't want to do squat */
2651 case -1:
2652 case 410: /* Must ignore this, it gets sent when we resize */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002653#ifdef PDCURSES
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002654 case 541: /* ???? */
2655 case 542: /* Control and alt in Windows *shrug* */
Chris Allegretta72623582000-11-29 23:43:28 +00002656 case 543: /* Right ctrl key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002657 case 544:
Chris Allegretta72623582000-11-29 23:43:28 +00002658 case 545: /* Right alt key */
Chris Allegrettaad1dacc2000-09-21 04:25:45 +00002659#endif
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002660
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002661 break;
2662 default:
2663#ifdef DEBUG
2664 fprintf(stderr, "I got %c (%d)!\n", kbinput, kbinput);
2665#endif
2666 /* We no longer stop unhandled sequences so that people with
2667 odd character sets can type... */
2668
2669 if (ISSET(VIEW_MODE)) {
2670 print_view_warning();
2671 break;
2672 }
2673 do_char(kbinput);
2674 }
Chris Allegretta756f2202000-09-01 13:32:47 +00002675 if (ISSET(CONSTUPDATE)) {
2676 if (ISSET(DISABLE_CURPOS))
2677 UNSET(DISABLE_CURPOS);
2678 else
2679 do_cursorpos();
2680 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002681
2682 reset_cursor();
2683 wrefresh(edit);
2684 keyhandled = 0;
2685 }
2686
2687 getchar();
2688 finish(0);
2689
2690}